[geary/mjog/rfc822-cleanup: 10/15] Geary.RFC822: Clean up message data interfaces and classes
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/rfc822-cleanup: 10/15] Geary.RFC822: Clean up message data interfaces and classes
- Date: Wed, 6 May 2020 05:00:06 +0000 (UTC)
commit 6e7631b8d30febe0f4c238e2e5a3670f3d9e52d4
Author: Michael Gratton <mike vee net>
Date: Wed May 6 11:27:00 2020 +1000
Geary.RFC822: Clean up message data interfaces and classes
Split Geary.RFC822.MessageData interface up into DecodedMessageData and
EncodedMessageData so the difference between the two is clear and they
can't be used interchangeably.
Add `DecodedMessageData::to_rfc822_string` to provide a common interface
for round-tripping decoded data.
Update all classes to implement one of these and follow the same general
API patterns.
src/engine/imap-db/imap-db-message-row.vala | 8 +-
src/engine/imap/api/imap-folder-session.vala | 4 +-
.../imap/response/imap-fetch-data-decoder.vala | 4 +-
src/engine/rfc822/rfc822-mailbox-address.vala | 5 +-
src/engine/rfc822/rfc822-mailbox-addresses.vala | 3 +-
src/engine/rfc822/rfc822-message-data.vala | 174 ++++++++++++++-------
test/engine/app/app-conversation-monitor-test.vala | 2 +-
test/engine/app/app-conversation-set-test.vala | 2 +-
test/engine/app/app-conversation-test.vala | 2 +-
test/engine/rfc822/rfc822-message-data-test.vala | 10 +-
10 files changed, 137 insertions(+), 77 deletions(-)
---
diff --git a/src/engine/imap-db/imap-db-message-row.vala b/src/engine/imap-db/imap-db-message-row.vala
index f7b065dc6..0b09a8cd4 100644
--- a/src/engine/imap-db/imap-db-message-row.vala
+++ b/src/engine/imap-db/imap-db-message-row.vala
@@ -106,7 +106,7 @@ private class Geary.ImapDB.MessageRow {
if (fields.is_all_set(Geary.Email.Field.DATE)) {
try {
email.set_send_date(
- !String.is_empty(date) ? new RFC822.Date(date) : null
+ !String.is_empty(date) ? new RFC822.Date.from_rfc822_string(date) : null
);
} catch (GLib.Error err) {
debug("Error loading message date from db: %s", err.message);
@@ -133,7 +133,7 @@ private class Geary.ImapDB.MessageRow {
}
if (fields.is_all_set(Geary.Email.Field.SUBJECT))
- email.set_message_subject(new RFC822.Subject.decode(subject ?? ""));
+ email.set_message_subject(new RFC822.Subject.from_rfc822_string(subject ?? ""));
if (fields.is_all_set(Geary.Email.Field.HEADER))
email.set_message_header(new RFC822.Header(header ?? Memory.EmptyBuffer.instance));
@@ -191,7 +191,7 @@ private class Geary.ImapDB.MessageRow {
// null if empty
if (email.fields.is_all_set(Geary.Email.Field.DATE)) {
- date = (email.date != null) ? email.date.original : null;
+ date = (email.date != null) ? email.date.to_rfc822_string() : null;
date_time_t = (email.date != null) ? email.date.value.to_unix() : -1;
fields = fields.set(Geary.Email.Field.DATE);
@@ -222,7 +222,7 @@ private class Geary.ImapDB.MessageRow {
}
if (email.fields.is_all_set(Geary.Email.Field.SUBJECT)) {
- subject = (email.subject != null) ? email.subject.original : null;
+ subject = (email.subject != null) ? email.subject.to_rfc822_string() : null;
fields = fields.set(Geary.Email.Field.SUBJECT);
}
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
index a934fecc5..e0e376870 100644
--- a/src/engine/imap/api/imap-folder-session.vala
+++ b/src/engine/imap/api/imap-folder-session.vala
@@ -901,7 +901,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
RFC822.Date? date = null;
if (!String.is_empty(value)) {
try {
- date = new RFC822.Date(value);
+ date = new RFC822.Date.from_rfc822_string(value);
} catch (GLib.Error err) {
warning(
"Error parsing date from FETCH response: %s",
@@ -979,7 +979,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
if (required_but_not_set(Geary.Email.Field.SUBJECT, required_fields, email)) {
string? value = headers.get("Subject");
if (value != null)
- email.set_message_subject(new RFC822.Subject.decode(value));
+ email.set_message_subject(new RFC822.Subject.from_rfc822_string(value));
else
email.set_message_subject(null);
}
diff --git a/src/engine/imap/response/imap-fetch-data-decoder.vala
b/src/engine/imap/response/imap-fetch-data-decoder.vala
index 8f9f42b92..2d3cfce6d 100644
--- a/src/engine/imap/response/imap-fetch-data-decoder.vala
+++ b/src/engine/imap/response/imap-fetch-data-decoder.vala
@@ -148,7 +148,7 @@ public class Geary.Imap.EnvelopeDecoder : Geary.Imap.FetchDataDecoder {
Geary.RFC822.Date? sent_date = null;
if (sent != null) {
try {
- sent_date = new RFC822.Date(sent.ascii);
+ sent_date = new RFC822.Date.from_rfc822_string(sent.ascii);
} catch (GLib.Error err) {
debug(
"Error parsing sent date from FETCH envelope: %s",
@@ -159,7 +159,7 @@ public class Geary.Imap.EnvelopeDecoder : Geary.Imap.FetchDataDecoder {
return new Envelope(
sent_date,
- new Geary.RFC822.Subject.decode(subject.ascii),
+ new Geary.RFC822.Subject.from_rfc822_string(subject.ascii),
parse_addresses(from), parse_addresses(sender), parse_addresses(reply_to),
(to != null) ? parse_addresses(to) : null,
(cc != null) ? parse_addresses(cc) : null,
diff --git a/src/engine/rfc822/rfc822-mailbox-address.vala b/src/engine/rfc822/rfc822-mailbox-address.vala
index 7b9ea3f68..f4f622cea 100644
--- a/src/engine/rfc822/rfc822-mailbox-address.vala
+++ b/src/engine/rfc822/rfc822-mailbox-address.vala
@@ -17,9 +17,10 @@
* See [[https://tools.ietf.org/html/rfc5322#section-3.4]]
*/
public class Geary.RFC822.MailboxAddress :
+ Geary.MessageData.AbstractMessageData,
Geary.MessageData.SearchableMessageData,
Gee.Hashable<MailboxAddress>,
- BaseObject {
+ DecodedMessageData {
private static unichar[] ATEXT = {
'!', '#', '$', '%', '&', '\'', '*', '+', '-',
@@ -551,7 +552,7 @@ public class Geary.RFC822.MailboxAddress :
*
* @see to_rfc822_string
*/
- public string to_string() {
+ public override string to_string() {
return to_rfc822_string();
}
diff --git a/src/engine/rfc822/rfc822-mailbox-addresses.vala b/src/engine/rfc822/rfc822-mailbox-addresses.vala
index 1e2bdc7c7..5890f23f6 100644
--- a/src/engine/rfc822/rfc822-mailbox-addresses.vala
+++ b/src/engine/rfc822/rfc822-mailbox-addresses.vala
@@ -17,7 +17,8 @@
public class Geary.RFC822.MailboxAddresses :
Geary.MessageData.AbstractMessageData,
Geary.MessageData.SearchableMessageData,
- Geary.RFC822.MessageData, Gee.Hashable<MailboxAddresses> {
+ Gee.Hashable<MailboxAddresses>,
+ DecodedMessageData {
/**
diff --git a/src/engine/rfc822/rfc822-message-data.vala b/src/engine/rfc822/rfc822-message-data.vala
index fdd75ccd3..e228b3443 100644
--- a/src/engine/rfc822/rfc822-message-data.vala
+++ b/src/engine/rfc822/rfc822-message-data.vala
@@ -1,46 +1,75 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
+/*
+ * Copyright © 2016 Software Freedom Conservancy Inc.
+ * Copyright © 2020 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.
*/
/**
- * RFC822.MessageData represents a base class for all the various elements that may be present in
- * an RFC822 message header. Note that some common elements (such as MailAccount) are not
- * MessageData because they exist in an RFC822 header in list (i.e. multiple email addresses) form.
+ * A base interface for objects that represent decoded RFC822 headers.
+ *
+ * The value of these objects is the decoded form of the header
+ * data. Encoded forms can be obtained via {@link to_rfc822_string}.
*/
+public interface Geary.RFC822.DecodedMessageData :
+ Geary.MessageData.AbstractMessageData {
+
+ /** Returns an RFC822-safe string representation of the data. */
+ public abstract string to_rfc822_string();
-public interface Geary.RFC822.MessageData : Geary.MessageData.AbstractMessageData {
}
/**
- * An RFC822 Message-ID.
+ * A base interface for objects that represent encoded RFC822 header data.
*
- * MessageID will normalize all strings so that they begin and end with the proper brackets ("<" and
- * ">").
+ * The value of these objects is the RFC822 encoded form of the header
+ * data. Decoded forms can be obtained via means specific to
+ * implementations of this interface.
*/
-public class Geary.RFC822.MessageID : Geary.MessageData.StringMessageData, Geary.RFC822.MessageData {
+public interface Geary.RFC822.EncodedMessageData :
+ Geary.MessageData.BlockMessageData {
+
+}
+
+/**
+ * A RFC822 Message-ID.
+ *
+ * The decoded form of the id is the `addr-spec` portion, that is,
+ * without the leading `<` and tailing `>`.
+ */
+public class Geary.RFC822.MessageID :
+ Geary.MessageData.StringMessageData, DecodedMessageData {
+
+ private string rfc822;
+
public MessageID(string value) {
- string? normalized = normalize(value);
- base (normalized ?? value);
+ base(value);
}
- // Adds brackets if required, null if no change required
- private static string? normalize(string value) {
- bool needs_prefix = !value.has_prefix("<");
- bool needs_suffix = !value.has_suffix(">");
- if (!needs_prefix && !needs_suffix)
- return null;
+ public MessageID.from_rfc822_string(string rfc822) {
+ base(GMime.utils_decode_message_id(rfc822));
+ this.rfc822 = rfc822;
+ }
- return "%s%s%s".printf(needs_prefix ? "<" : "", value, needs_suffix ? ">" : "");
+ /**
+ * Returns the {@link Date} in RFC 822 format.
+ */
+ public string to_rfc822_string() {
+ if (this.rfc822 == null) {
+ this.rfc822 = "<%s>".printf(this.value);
+ }
+ return this.rfc822;
}
+
}
/**
* A immutable list of RFC822 Message-ID values.
*/
-public class Geary.RFC822.MessageIDList : Geary.MessageData.AbstractMessageData, Geary.RFC822.MessageData {
- public Gee.List<MessageID> list { get; private set; }
+public class Geary.RFC822.MessageIDList :
+ Geary.MessageData.AbstractMessageData,
+ DecodedMessageData {
/** Returns the number of ids in this list. */
@@ -189,71 +218,87 @@ public class Geary.RFC822.MessageIDList : Geary.MessageData.AbstractMessageData,
}
-public class Geary.RFC822.Date : Geary.RFC822.MessageData, Geary.MessageData.AbstractMessageData,
- Gee.Hashable<Geary.RFC822.Date> {
+public class Geary.RFC822.Date :
+ Geary.MessageData.AbstractMessageData,
+ Gee.Hashable<Geary.RFC822.Date>,
+ DecodedMessageData {
+
+
+ public GLib.DateTime value { get; private set; }
+
+ private string? rfc822;
- public string original { get; private set; }
- public DateTime value { get; private set; }
- public Date(string rfc822) throws RFC822Error {
+ public Date(GLib.DateTime datetime) {
+ this.value = datetime;
+ this.rfc822 = null;
+ }
+
+ public Date.from_rfc822_string(string rfc822) throws RFC822Error {
var date = GMime.utils_header_decode_date(rfc822);
if (date == null) {
throw new RFC822Error.INVALID("Not ISO-8601 date: %s", rfc822);
}
+ this.rfc822 = rfc822;
this.value = date;
- this.original = rfc822;
- }
-
- public Date.from_date_time(DateTime datetime) {
- this.original = null;
- this.value = datetime;
}
/**
* Returns the {@link Date} in RFC 822 format.
*/
public string to_rfc822_string() {
- return GMime.utils_header_format_date(this.value);
- }
-
- /**
- * Returns {@link Date} for transmission.
- *
- * @see to_rfc822_string
- */
- public virtual string serialize() {
- return to_rfc822_string();
+ if (this.rfc822 == null) {
+ this.rfc822 = GMime.utils_header_format_date(this.value);
+ }
+ return this.rfc822;
}
public virtual bool equal_to(Geary.RFC822.Date other) {
- return (this != other) ? value.equal(other.value) : true;
+ return this == other || this.value.equal(other.value);
}
public virtual uint hash() {
- return value.hash();
+ return this.value.hash();
}
public override string to_string() {
- return original ?? value.to_string();
+ return this.value.to_string();
}
}
-public class Geary.RFC822.Subject : Geary.MessageData.StringMessageData,
- Geary.MessageData.SearchableMessageData, Geary.RFC822.MessageData {
+public class Geary.RFC822.Subject :
+ Geary.MessageData.StringMessageData,
+ Geary.MessageData.SearchableMessageData,
+ DecodedMessageData {
+
public const string REPLY_PREFACE = "Re:";
public const string FORWARD_PREFACE = "Fwd:";
- public string original { get; private set; }
+
+ private string rfc822;
+
public Subject(string value) {
- base (value);
- original = value;
+ base(value);
+ this.rfc822 = null;
}
- public Subject.decode(string value) {
- base (GMime.utils_header_decode_text(Geary.RFC822.get_parser_options(), value));
- original = value;
+ public Subject.from_rfc822_string(string rfc822) {
+ base(GMime.utils_header_decode_text(get_parser_options(), rfc822));
+ this.rfc822 = rfc822;
+ }
+
+ /**
+ * Returns the subject line encoded for an RFC 822 message.
+ */
+ public string to_rfc822_string() {
+ if (this.rfc822 == null) {
+ this.rfc822 = GMime.utils_header_encode_text(
+ get_format_options(), this.value, null
+ );
+ }
+ return this.rfc822;
}
public bool is_reply() {
@@ -312,9 +357,13 @@ public class Geary.RFC822.Subject : Geary.MessageData.StringMessageData,
public string to_searchable_string() {
return value;
}
+
}
-public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC822.MessageData {
+public class Geary.RFC822.Header :
+ Geary.MessageData.BlockMessageData, EncodedMessageData {
+
+
private GMime.Message? message = null;
private string[]? names = null;
@@ -353,22 +402,30 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC
}
return this.names;
}
+
}
-public class Geary.RFC822.Text : Geary.MessageData.BlockMessageData, Geary.RFC822.MessageData {
+public class Geary.RFC822.Text :
+ Geary.MessageData.BlockMessageData, EncodedMessageData {
+
public Text(Memory.Buffer buffer) {
- base ("RFC822.Text", buffer);
+ base("RFC822.Text", buffer);
}
+
}
-public class Geary.RFC822.Full : Geary.MessageData.BlockMessageData, Geary.RFC822.MessageData {
+public class Geary.RFC822.Full :
+ Geary.MessageData.BlockMessageData, EncodedMessageData {
+
public Full(Memory.Buffer buffer) {
- base ("RFC822.Full", buffer);
+ base("RFC822.Full", buffer);
}
+
}
-// Used for decoding preview text.
+/** Represents text providing a preview of an email's body. */
public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
+
public PreviewText(Memory.Buffer _buffer) {
base (_buffer);
}
@@ -415,4 +472,5 @@ public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
public PreviewText.from_string(string preview) {
base (new Geary.Memory.StringBuffer(preview));
}
+
}
diff --git a/test/engine/app/app-conversation-monitor-test.vala
b/test/engine/app/app-conversation-monitor-test.vala
index 0dec7655f..3224cf8b4 100644
--- a/test/engine/app/app-conversation-monitor-test.vala
+++ b/test/engine/app/app-conversation-monitor-test.vala
@@ -434,7 +434,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
references.message_id
);
}
- email.set_send_date(new Geary.RFC822.Date.from_date_time(now));
+ email.set_send_date(new RFC822.Date(now));
email.set_email_properties(new MockEmailProperties(now));
email.set_full_references(mid, null, refs_list);
return email;
diff --git a/test/engine/app/app-conversation-set-test.vala b/test/engine/app/app-conversation-set-test.vala
index 1250ad6a2..2966e1341 100644
--- a/test/engine/app/app-conversation-set-test.vala
+++ b/test/engine/app/app-conversation-set-test.vala
@@ -489,7 +489,7 @@ class Geary.App.ConversationSetTest : TestCase {
references.message_id
);
}
- email.set_send_date(new Geary.RFC822.Date.from_date_time(now));
+ email.set_send_date(new RFC822.Date(now));
email.set_email_properties(new MockEmailProperties(now));
email.set_full_references(mid, null, refs_list);
return email;
diff --git a/test/engine/app/app-conversation-test.vala b/test/engine/app/app-conversation-test.vala
index e6c731431..03ebd8f28 100644
--- a/test/engine/app/app-conversation-test.vala
+++ b/test/engine/app/app-conversation-test.vala
@@ -289,7 +289,7 @@ class Geary.App.ConversationTest : TestCase {
);
email.set_full_references(mid, null, null);
email.set_email_properties(new MockEmailProperties(now));
- email.set_send_date(new Geary.RFC822.Date.from_date_time(now));
+ email.set_send_date(new RFC822.Date(now));
return email;
}
diff --git a/test/engine/rfc822/rfc822-message-data-test.vala
b/test/engine/rfc822/rfc822-message-data-test.vala
index 504efaa0c..dd9b2bf36 100644
--- a/test/engine/rfc822/rfc822-message-data-test.vala
+++ b/test/engine/rfc822/rfc822-message-data-test.vala
@@ -61,7 +61,7 @@ class Geary.RFC822.MessageDataTest : TestCase {
public void date_from_rfc822() throws GLib.Error {
const string FULL_HOUR_TZ = "Thu, 28 Feb 2019 00:00:00 -0100";
- Date full_hour_tz = new Date(FULL_HOUR_TZ);
+ Date full_hour_tz = new Date.from_rfc822_string(FULL_HOUR_TZ);
assert_int64(
((int64) (-1 * 3600)) * 1000 * 1000,
full_hour_tz.value.get_utc_offset(),
@@ -81,7 +81,7 @@ class Geary.RFC822.MessageDataTest : TestCase {
);
const string HALF_HOUR_TZ = "Thu, 28 Feb 2019 00:00:00 +1030";
- Date half_hour_tz = new Date(HALF_HOUR_TZ);
+ Date half_hour_tz = new Date.from_rfc822_string(HALF_HOUR_TZ);
assert_int64(
((int64) (10.5 * 3600)) * 1000 * 1000,
half_hour_tz.value.get_utc_offset()
@@ -96,15 +96,15 @@ class Geary.RFC822.MessageDataTest : TestCase {
public void date_to_rfc822() throws GLib.Error {
const string FULL_HOUR_TZ = "Thu, 28 Feb 2019 00:00:00 -0100";
- Date full_hour_tz = new Date(FULL_HOUR_TZ);
+ Date full_hour_tz = new Date.from_rfc822_string(FULL_HOUR_TZ);
assert_string(FULL_HOUR_TZ, full_hour_tz.to_rfc822_string());
const string HALF_HOUR_TZ = "Thu, 28 Feb 2019 00:00:00 +1030";
- Date half_hour_tz = new Date(HALF_HOUR_TZ);
+ Date half_hour_tz = new Date.from_rfc822_string(HALF_HOUR_TZ);
assert_string(HALF_HOUR_TZ, half_hour_tz.to_rfc822_string());
const string NEG_HALF_HOUR_TZ = "Thu, 28 Feb 2019 00:00:00 -1030";
- Date neg_half_hour_tz = new Date(NEG_HALF_HOUR_TZ);
+ Date neg_half_hour_tz = new Date.from_rfc822_string(NEG_HALF_HOUR_TZ);
assert_string(NEG_HALF_HOUR_TZ, neg_half_hour_tz.to_rfc822_string());
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]