From ddb3a899fbc074e6df8e4bb0ee23ea11af7113d3 Mon Sep 17 00:00:00 2001 From: Michael Gratton Date: Fri, 1 May 2020 15:40:18 +1000 Subject: [PATCH] Geary.Imap: Add Quirks object to collect all IMAP service quirk config --- src/console/main.vala | 3 ++- src/engine/api/geary-engine.vala | 5 ++++- src/engine/imap/api/imap-client-service.vala | 15 +++++++++++--- src/engine/imap/api/imap-quirks.vala | 18 +++++++++++++++++ .../transport/imap-client-connection.vala | 7 ++++++- .../imap/transport/imap-client-session.vala | 6 ++++-- .../imap/transport/imap-deserializer.vala | 7 ++++++- src/engine/meson.build | 1 + .../imap-client-connection-test.vala | 8 +++++--- .../transport/imap-client-session-test.vala | 20 +++++++++---------- .../transport/imap-deserializer-test.vala | 2 +- test/integration/imap/client-session.vala | 5 ++++- 12 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 src/engine/imap/api/imap-quirks.vala diff --git a/src/console/main.vala b/src/console/main.vala index 70e961f8..b114c7e3 100644 --- a/src/console/main.vala +++ b/src/console/main.vala @@ -315,7 +315,8 @@ class ImapConsole : Gtk.Window { new GLib.NetworkAddress(args[0], Geary.Imap.IMAP_TLS_PORT), method, IMAP_TIMEOUT_SEC - ) + ), + new Geary.Imap.Quirks() ); cx.sent_command.connect(on_sent_command); diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala index 157eb2b1..5f8f7143 100644 --- a/src/engine/api/geary-engine.vala +++ b/src/engine/api/geary-engine.vala @@ -284,7 +284,10 @@ public class Geary.Engine : BaseObject { (security, cx) => account.untrusted_host(service, security, cx) ); - var client = new Imap.ClientSession(endpoint); + var client = new Imap.ClientSession( + endpoint, + Imap.ClientService.new_quirks_for_provider(account.service_provider) + ); GLib.Error? imap_err = null; try { yield client.connect_async( diff --git a/src/engine/imap/api/imap-client-service.vala b/src/engine/imap/api/imap-client-service.vala index a9feabd9..80fe752b 100644 --- a/src/engine/imap/api/imap-client-service.vala +++ b/src/engine/imap/api/imap-client-service.vala @@ -39,6 +39,12 @@ public class Geary.Imap.ClientService : Geary.ClientService { private const int CHECK_NOOP_THRESHOLD_SEC = 5; + public static Quirks new_quirks_for_provider(ServiceProvider provider) { + var quirks = new Quirks(); + return quirks; + } + + /** * Set to zero or negative value if keepalives should be disabled when a connection has not * selected a mailbox. (This is not recommended.) @@ -101,6 +107,8 @@ public class Geary.Imap.ClientService : Geary.ClientService { get { return LOGGING_DOMAIN; } } + private Quirks quirks; + private Nonblocking.Mutex sessions_mutex = new Nonblocking.Mutex(); private Gee.Set all_sessions = new Gee.HashSet(); @@ -112,9 +120,10 @@ public class Geary.Imap.ClientService : Geary.ClientService { public ClientService(AccountInformation account, - ServiceInformation service, + ServiceInformation configuration, Endpoint remote) { - base(account, service, remote); + base(account, configuration, remote); + this.quirks = new_quirks_for_provider(account.service_provider); } /** @@ -445,7 +454,7 @@ public class Geary.Imap.ClientService : Geary.ClientService { throw new ImapError.UNAUTHENTICATED("Token not loaded"); } - ClientSession new_session = new ClientSession(remote); + ClientSession new_session = new ClientSession(remote, this.quirks); new_session.set_logging_parent(this); yield new_session.connect_async( ClientSession.DEFAULT_GREETING_TIMEOUT_SEC, cancellable diff --git a/src/engine/imap/api/imap-quirks.vala b/src/engine/imap/api/imap-quirks.vala new file mode 100644 index 00000000..cce53d46 --- /dev/null +++ b/src/engine/imap/api/imap-quirks.vala @@ -0,0 +1,18 @@ +/* + * Copyright © 2019-2020 Michael Gratton + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +/** + * A set of quirks for a specific IMAP service. + */ +public class Geary.Imap.Quirks : BaseObject { + + + /** The set of additional characters allowed in an IMAP flag. */ + public string? flag_atom_exceptions { get; set; } + + +} diff --git a/src/engine/imap/transport/imap-client-connection.vala b/src/engine/imap/transport/imap-client-connection.vala index ab8f8dc8..756d7bb7 100644 --- a/src/engine/imap/transport/imap-client-connection.vala +++ b/src/engine/imap/transport/imap-client-connection.vala @@ -65,6 +65,7 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source { private Geary.Endpoint endpoint; private int cx_id; + private Quirks quirks; private IOStream? cx = null; private Deserializer? deserializer = null; private Serializer? serializer = null; @@ -111,9 +112,11 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source { public ClientConnection( Geary.Endpoint endpoint, + Quirks quirks, uint command_timeout = Command.DEFAULT_RESPONSE_TIMEOUT_SEC, uint idle_timeout_sec = DEFAULT_IDLE_TIMEOUT_SEC) { this.endpoint = endpoint; + this.quirks = quirks; this.cx_id = next_cx_id++; this.command_timeout = command_timeout; this.idle_timer = new TimeoutManager.seconds( @@ -323,7 +326,9 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source { // Not buffering the Deserializer because it uses a // DataInputStream, which is already buffered - this.deserializer = new Deserializer(id, this.cx.input_stream); + this.deserializer = new Deserializer( + id, this.cx.input_stream, this.quirks + ); this.deserializer.bytes_received.connect(on_bytes_received); this.deserializer.deserialize_failure.connect(on_deserialize_failure); this.deserializer.end_of_stream.connect(on_eos); diff --git a/src/engine/imap/transport/imap-client-session.vala b/src/engine/imap/transport/imap-client-session.vala index a7c1ae53..13957422 100644 --- a/src/engine/imap/transport/imap-client-session.vala +++ b/src/engine/imap/transport/imap-client-session.vala @@ -296,6 +296,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source { private Gee.List shared_namespaces = new Gee.ArrayList(); private Endpoint imap_endpoint; + private Quirks quirks; private Geary.State.Machine fsm; private ClientConnection? cx = null; @@ -344,8 +345,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source { public signal void status(StatusData status_data); - public ClientSession(Endpoint imap_endpoint) { + public ClientSession(Endpoint imap_endpoint, Quirks quirks) { this.imap_endpoint = imap_endpoint; + this.quirks = quirks; Geary.State.Mapping[] mappings = { new Geary.State.Mapping(State.NOT_CONNECTED, Event.CONNECT, on_connect), @@ -774,7 +776,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source { MachineParams params = (MachineParams) object; assert(cx == null); - cx = new ClientConnection(imap_endpoint); + cx = new ClientConnection(imap_endpoint, this.quirks); cx.set_logging_parent(this); cx.sent_command.connect(on_network_sent_command); cx.send_failure.connect(on_network_send_error); diff --git a/src/engine/imap/transport/imap-deserializer.vala b/src/engine/imap/transport/imap-deserializer.vala index 014d73ae..6f0d4b4d 100644 --- a/src/engine/imap/transport/imap-deserializer.vala +++ b/src/engine/imap/transport/imap-deserializer.vala @@ -85,6 +85,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source { private weak Logging.Source? _logging_parent = null; private string identifier; + private Quirks quirks; private DataInputStream input; private Geary.State.Machine fsm; @@ -153,13 +154,17 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source { public signal void end_of_stream(); - public Deserializer(string identifier, GLib.InputStream input) { + public Deserializer(string identifier, + GLib.InputStream input, + Quirks quirks) { this.identifier = identifier; this.input = new GLib.DataInputStream(input); this.input.set_close_base_stream(false); this.input.set_newline_type(CR_LF); + this.quirks = quirks; + Geary.State.Mapping[] mappings = { new Geary.State.Mapping(State.TAG, Event.CHAR, on_tag_char), new Geary.State.Mapping(State.TAG, Event.EOS, on_eos), diff --git a/src/engine/meson.build b/src/engine/meson.build index d026575d..ee664cf6 100644 --- a/src/engine/meson.build +++ b/src/engine/meson.build @@ -93,6 +93,7 @@ geary_engine_vala_sources = files( 'imap/api/imap-folder-properties.vala', 'imap/api/imap-folder-root.vala', 'imap/api/imap-folder-session.vala', + 'imap/api/imap-quirks.vala', 'imap/api/imap-session-object.vala', 'imap/command/imap-append-command.vala', 'imap/command/imap-authenticate-command.vala', diff --git a/test/engine/imap/transport/imap-client-connection-test.vala b/test/engine/imap/transport/imap-client-connection-test.vala index cbbf9a78..9bc745da 100644 --- a/test/engine/imap/transport/imap-client-connection-test.vala +++ b/test/engine/imap/transport/imap-client-connection-test.vala @@ -38,7 +38,7 @@ class Geary.Imap.ClientConnectionTest : TestCase { } public void connect_disconnect() throws GLib.Error { - var test_article = new ClientConnection(new_endpoint()); + var test_article = new ClientConnection(new_endpoint(), new Quirks()); test_article.connect_async.begin(null, this.async_completion); test_article.connect_async.end(async_result()); @@ -69,7 +69,7 @@ class Geary.Imap.ClientConnectionTest : TestCase { const int IDLE_TIMEOUT = 1; var test_article = new ClientConnection( - new_endpoint(), COMMAND_TIMEOUT, IDLE_TIMEOUT + new_endpoint(), new Quirks(), COMMAND_TIMEOUT, IDLE_TIMEOUT ); test_article.connect_async.begin(null, this.async_completion); test_article.connect_async.end(async_result()); @@ -123,7 +123,9 @@ class Geary.Imap.ClientConnectionTest : TestCase { bool recv_fail = false; bool timed_out = false; - var test_article = new ClientConnection(new_endpoint(), TIMEOUT); + var test_article = new ClientConnection( + new_endpoint(), new Quirks(), TIMEOUT + ); test_article.sent_command.connect(() => { sent = true; }); test_article.receive_failure.connect(() => { recv_fail = true; }); test_article.connect_async.begin(null, this.async_completion); diff --git a/test/engine/imap/transport/imap-client-session-test.vala b/test/engine/imap/transport/imap-client-session-test.vala index 8e2195a8..f1a9e9e5 100644 --- a/test/engine/imap/transport/imap-client-session-test.vala +++ b/test/engine/imap/transport/imap-client-session-test.vala @@ -43,7 +43,7 @@ class Geary.Imap.ClientSessionTest : TestCase { ); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -69,7 +69,7 @@ class Geary.Imap.ClientSessionTest : TestCase { ); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); test_article.connect_async.begin( CONNECT_TIMEOUT, null, this.async_completion ); @@ -87,7 +87,7 @@ class Geary.Imap.ClientSessionTest : TestCase { public void connect_timeout() throws GLib.Error { this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); GLib.Timer timer = new GLib.Timer(); timer.start(); @@ -115,7 +115,7 @@ class Geary.Imap.ClientSessionTest : TestCase { ); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); test_article.connect_async.begin( CONNECT_TIMEOUT, null, this.async_completion ); @@ -147,7 +147,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a001 OK ohhai"); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -184,7 +184,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a001 OK laters"); this.server.add_script_line(DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -215,7 +215,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a002 OK laters"); this.server.add_script_line(DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -260,7 +260,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a004 OK there"); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -304,7 +304,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a002 OK there"); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( @@ -367,7 +367,7 @@ class Geary.Imap.ClientSessionTest : TestCase { this.server.add_script_line(SEND_LINE, "a003 OK there"); this.server.add_script_line(WAIT_FOR_DISCONNECT, ""); - var test_article = new ClientSession(new_endpoint()); + var test_article = new ClientSession(new_endpoint(), new Quirks()); assert_true(test_article.get_protocol_state() == NOT_CONNECTED); test_article.connect_async.begin( diff --git a/test/engine/imap/transport/imap-deserializer-test.vala b/test/engine/imap/transport/imap-deserializer-test.vala index d7380eaa..e9a34d88 100644 --- a/test/engine/imap/transport/imap-deserializer-test.vala +++ b/test/engine/imap/transport/imap-deserializer-test.vala @@ -47,7 +47,7 @@ class Geary.Imap.DeserializerTest : TestCase { public override void set_up() { this.stream = new MemoryInputStream(); - this.deser = new Deserializer(ID, this.stream); + this.deser = new Deserializer(ID, this.stream, new Quirks()); } public override void tear_down() { diff --git a/test/integration/imap/client-session.vala b/test/integration/imap/client-session.vala index d4f1c3d8..ad48e545 100644 --- a/test/integration/imap/client-session.vala +++ b/test/integration/imap/client-session.vala @@ -28,7 +28,10 @@ class Integration.Imap.ClientSession : TestCase { public override void set_up() { this.session = new Geary.Imap.ClientSession( - this.config.target + this.config.target, + Geary.Imap.ClientService.new_quirks_for_provider( + this.config.provider + ) ); }