Geary.RFC822.MessageID: Replace GMime parser with more lax parser

Support parsing message IDs with the form `<add-spec>` (per the RFC)
but also `(add-spec)` and `add-spec`.

Add unit tests.
This commit is contained in:
Michael Gratton 2020-08-22 16:23:07 +10:00
parent 4e50822674
commit eb3a8b0fe4
2 changed files with 94 additions and 3 deletions

View file

@ -46,10 +46,45 @@ public class Geary.RFC822.MessageID :
}
public MessageID.from_rfc822_string(string rfc822) throws Error {
if (String.is_empty_or_whitespace(rfc822)) {
throw new Error.INVALID("Empty RFC822 message id: %s", rfc822);
int len = rfc822.length;
int start = 0;
while (start < len && rfc822[start].isspace()) {
start += 1;
}
base(GMime.utils_decode_message_id(rfc822));
char end_delim = 0;
bool break_on_space = false;
if (start < len) {
switch (rfc822[start]) {
case '<':
// Standard delim
start += 1;
end_delim = '>';
break;
case '(':
// Non-standard delim
start += 1;
end_delim = ')';
break;
default:
// no other supported delimiters, so just end at white
// space or EOS
break_on_space = true;
break;
}
}
int end = start + 1;
while (end < len &&
rfc822[end] != end_delim &&
(!break_on_space || !rfc822[end].isspace())) {
end += 1;
}
if (start + 1 >= end) {
throw new Error.INVALID("Empty RFC822 message id");
}
base(rfc822.slice(start, end));
}
/**

View file

@ -15,6 +15,7 @@ class Geary.RFC822.MessageDataTest : TestCase {
add_test("header_from_rfc822", header_from_rfc822);
add_test("header_names_from_rfc822", header_names_from_rfc822);
add_test("PreviewText.with_header", preview_text_with_header);
add_test("MessageId.from_rfc822_string", message_id_from_rfc822_string);
add_test("MessageId.to_rfc822_string", message_id_to_rfc822_string);
add_test("MessageIdList.from_rfc822_string", message_id_list_from_rfc822_string);
add_test("MessageIdList.merge", message_id_list_merge);
@ -111,6 +112,61 @@ class Geary.RFC822.MessageDataTest : TestCase {
assert_equal(neg_half_hour_tz.to_rfc822_string(), NEG_HALF_HOUR_TZ);
}
public void message_id_from_rfc822_string() throws GLib.Error {
assert_equal(
new MessageID.from_rfc822_string("<note_895184@gitlab.gnome.org>").value,
"note_895184@gitlab.gnome.org"
);
assert_equal(
new MessageID.from_rfc822_string(" <note_895184@gitlab.gnome.org>\n").value,
"note_895184@gitlab.gnome.org"
);
assert_equal(
new MessageID.from_rfc822_string("note_895184@gitlab.gnome.org").value,
"note_895184@gitlab.gnome.org"
);
assert_equal(
new MessageID.from_rfc822_string(" note_895184@gitlab.gnome.org\n").value,
"note_895184@gitlab.gnome.org"
);
assert_equal(
new MessageID.from_rfc822_string("(note_895184@gitlab.gnome.org)").value,
"note_895184@gitlab.gnome.org"
);
assert_equal(
new MessageID.from_rfc822_string("<note_895184>").value,
"note_895184"
);
assert_equal(
new MessageID.from_rfc822_string("<note 895184>").value,
"note 895184"
);
assert_equal(
new MessageID.from_rfc822_string("<id1> <id2>").value,
"id1"
);
try {
new MessageID.from_rfc822_string("");
assert_not_reached();
} catch (GLib.Error err) {
assert_error(err, new Error.INVALID(""));
}
try {
new MessageID.from_rfc822_string(" ");
assert_not_reached();
} catch (GLib.Error err) {
assert_error(err, new Error.INVALID(""));
}
try {
new MessageID.from_rfc822_string(" \n");
assert_not_reached();
} catch (GLib.Error err) {
assert_error(err, new Error.INVALID(""));
}
}
public void message_id_to_rfc822_string() throws GLib.Error {
assert_equal(
new MessageID("note_895184@gitlab.gnome.org").to_rfc822_string(),