[geary] Fix crash when value of is:foo search op has not been translated.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Fix crash when value of is:foo search op has not been translated.
- Date: Tue, 31 May 2016 07:51:35 +0000 (UTC)
commit a2d32b802ed2a5a59dc159464e4f967cf42725a8
Author: Michael James Gratton <mike vee net>
Date: Tue May 31 16:59:01 2016 +1000
Fix crash when value of is:foo search op has not been translated.
Bug 766837
* src/engine/imap-db/imap-db-account.vala (Geary.ImapDB.Account): Use
constants for internal, i.e. non-translatable, search op names and
values so it's clear what they are.
(::extract_field_from_token): Handle all translation of search op names
and values here up front. Ensure that the value for the "is:" operator
is valid, treat the whole thing like a plain string if not. Add some
translation comments for those values so translators know what's up.
(::get_removal_conditions): Assume that if we have a "is:" field that
the values have already been translated to their internal form.
src/engine/imap-db/imap-db-account.vala | 187 ++++++++++++++++++++-----------
1 files changed, 124 insertions(+), 63 deletions(-)
---
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index 17b2c2c..db38d45 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -12,7 +12,30 @@ private class Geary.ImapDB.Account : BaseObject {
// i.e. unadorned mailbox addresses. Note that characters commonly used for wildcards or that
// would be interpreted as wildcards by SQLite are not included here.
private const unichar[] SEARCH_TERM_CONTINUATION_CHARS = { '-', '_', '.', '@' };
-
+
+ // Search operator field names, eg: "to:foo example com" or "is:unread"
+ private const string SEARCH_OP_ATTACHMENT = "attachment";
+ private const string SEARCH_OP_BCC = "bcc";
+ private const string SEARCH_OP_BODY = "body";
+ private const string SEARCH_OP_CC = "cc";
+ private const string SEARCH_OP_FROM = "from";
+ private const string SEARCH_OP_IS = "is";
+ private const string SEARCH_OP_SUBJECT = "subject";
+ private const string SEARCH_OP_TO = "to";
+
+ // Fields we allow the token to be "me" as in from:me.
+ private const string[] SEARCH_OP_ADDRESSABLE_FIELDS = {
+ SEARCH_OP_BCC,
+ SEARCH_OP_CC,
+ SEARCH_OP_FROM,
+ SEARCH_OP_TO,
+ };
+
+ // Search operator field values
+ private const string SEARCH_OP_VALUE_READ = "read";
+ private const string SEARCH_OP_VALUE_STARRED = "starred";
+ private const string SEARCH_OP_VALUE_UNREAD = "unread";
+
private class FolderReference : Geary.SmartReference {
public Geary.FolderPath path;
@@ -695,70 +718,108 @@ private class Geary.ImapDB.Account : BaseObject {
return (messages.size == 0 ? null : messages);
}
-
+
private string? extract_field_from_token(string[] parts, ref string token) {
// Map of user-supplied search field names to column names.
Gee.HashMap<string, string> field_names = new Gee.HashMap<string, string>();
- /// Can be typed in the search box like attachment:file.txt to find
- /// messages with attachments with a particular name. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("attachment"), "attachment");
- /// Can be typed in the search box like bcc:johndoe example com to find
- /// messages bcc'd to a particular person. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("bcc"), "bcc");
- /// Can be typed in the search box like body:word to find the word only
- /// if it occurs in the body of a message. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("body"), "body");
- /// Can be typed in the search box like cc:johndoe example com to find
- /// messages cc'd to a particular person. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("cc"), "cc");
- /// Can be typed in the search box like from:johndoe example com to
- /// find messages from a particular sender. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("from"), "from_field");
- /// Can be typed in the search box like subject:word to find the word
- /// only if it occurs in the subject of a message. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("subject"), "subject");
- /// Can be typed in the search box like to:johndoe example com to find
- /// messages received by a particular person. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("to"), "receivers");
- /// Can be typed in the search box like is:read, is:unread or is:starred
- /// to find messages that are read, unread, or starred. The translated
- /// string must match the string in Geary's help documentation.
- field_names.set(_("is"), "is");
-
- // Fields we allow the token to be "me" as in from:me.
- string[] addressable_fields = {
- _("bcc"), _("cc"), _("from"), _("to"),
- };
-
- // If they stopped at "field:", treat it as if they hadn't typed the :
+ /// Can be typed in the search box like attachment:file.txt to
+ /// find messages with attachments with a particular name.
+ /// The translated string must match the string in
+ /// "search.page" of the Geary User Guide.
+ field_names.set(_("attachment"), SEARCH_OP_ATTACHMENT);
+ /// Can be typed in the search box like
+ /// bcc:johndoe example com to find messages bcc'd to a
+ /// particular person. The translated string must match the
+ /// string in "search.page" of the Geary User Guide.
+ field_names.set(_("bcc"), SEARCH_OP_BCC);
+ /// Can be typed in the search box like body:word to find the
+ /// word only if it occurs in the body of a message. The
+ /// translated string must match the string in "search.page"
+ /// of the Geary User Guide.
+ field_names.set(_("body"), SEARCH_OP_BODY);
+ /// Can be typed in the search box like cc:johndoe example com
+ /// to find messages cc'd to a particular person. The
+ /// translated string must match the string in "search.page"
+ /// of the Geary User Guide.
+ field_names.set(_("cc"), SEARCH_OP_CC);
+ /// Can be typed in the search box like
+ /// from:johndoe example com to find messages from a
+ /// particular sender. The translated string must match the
+ /// string in "search.page" of the Geary User Guide.
+ field_names.set(_("from"), SEARCH_OP_FROM);
+ /// Can be typed in the search box like is:read, is:unread or
+ /// is:starred to find messages that are read, unread, or
+ /// starred. The translated string must match the string in
+ /// "search.page" of the Geary User Guide.
+ field_names.set(_("is"), SEARCH_OP_IS);
+ /// Can be typed in the search box like subject:word to find
+ /// the word only if it occurs in the subject of a message.
+ /// The translated string must match the string in
+ /// "search.page" of the Geary User Guide.
+ field_names.set(_("subject"), SEARCH_OP_SUBJECT);
+ /// Can be typed in the search box like to:johndoe example com
+ /// to find messages received by a particular person. The
+ /// translated string must match the string in "search.page"
+ /// of the Geary User Guide.
+ field_names.set(_("to"), SEARCH_OP_TO);
+
+ /// "me" can be typed like from:me or cc:me, etc. as a
+ /// shorthand to find mail to or from yourself in search. The
+ /// translated string must match the string in "search.page"
+ /// of the Geary User Guide.
+ string search_op_value_me = _("me");
+
+ Gee.HashMap<string, string> is_field_values = new Gee.HashMap<string, string>();
+ /// Can be typed in the search box after "is:" i.e.:
+ /// "is:read". Matches conversations that are flagged as read.
+ /// This must be a single word, or multiple words connected
+ /// via a dash ('-') or underscore ('_'). The translated
+ /// string must also match the string in "search.page" of the
+ /// Geary User Guide.
+ is_field_values.set(_("read"), SEARCH_OP_VALUE_READ);
+ /// Can be typed in the search box after "is:" i.e.:
+ /// "is:starred". Matches conversations that are flagged as
+ /// starred. This must be a single word, or multiple words
+ /// connected via a dash ('-') or underscore ('_'). The
+ /// translated string must also match the string in
+ /// "search.page" of the Geary User Guide.
+ is_field_values.set(_("starred"), SEARCH_OP_VALUE_STARRED);
+ /// Can be typed in the search box after "is:" i.e.:
+ /// "is:unread". Matches conversations that are flagged
+ /// unread. This must be a single word, or multiple words
+ /// connected via a dash ('-') or underscore ('_'). The
+ /// translated string must also match the string in
+ /// "search.page" of the Geary User Guide.
+ is_field_values.set(_("unread"), SEARCH_OP_VALUE_UNREAD);
+
+ string? field = null;
if (Geary.String.is_empty_or_whitespace(parts[1])) {
+ // User stopped at "field:", treat it as if they hadn't
+ // typed the ':'
token = parts[0];
- return null;
- }
-
- string key = parts[0].down();
- if (key in field_names.keys) {
- token = parts[1];
- if (key in addressable_fields) {
- // "me" can be typed like from:me or cc:me, etc. as a shorthand
- // to find mail to or from yourself in search. The translated
- // string must match the string in Geary's help documentation.
- if (token.down() == _("me"))
- token = account_information.email;
+ } else {
+ field = field_names.get(parts[0].down());
+ if (field == SEARCH_OP_IS) {
+ // An "is:..." search term
+ string? value = is_field_values.get(parts[1].down());
+ if (value != null) {
+ token = value;
+ } else {
+ // Unknown op value, pretend there is no search op
+ field = null;
+ }
+ } else if (field in SEARCH_OP_ADDRESSABLE_FIELDS &&
+ token.down() == search_op_value_me) {
+ // A "to:me", "cc:me", etc. term
+ token = account_information.email;
+ } else if (field != null) {
+ // Everything else
+ token = parts[1];
}
- return field_names.get(key);
}
-
- return null;
+ return field;
}
-
+
/**
* This method is used to convert an unquoted user-entered search terms into a stemmed search
* term.
@@ -1197,24 +1258,24 @@ private class Geary.ImapDB.Account : BaseObject {
return search_results.size == 0 ? null : search_results.keys;
}
-
+
private Gee.Map<Geary.NamedFlag, bool> get_removal_conditions(ImapDB.SearchQuery query) {
Gee.Map<Geary.NamedFlag, bool> removal_conditions = new Gee.HashMap<Geary.NamedFlag, bool>();
foreach (string? field in query.get_fields())
- if (field == "is") {
+ if (field == SEARCH_OP_IS) {
Gee.List<SearchTerm>? terms = query.get_search_terms(field);
foreach (SearchTerm term in terms)
- if (term.parsed.down() == _("read"))
+ if (term.parsed == SEARCH_OP_VALUE_READ)
removal_conditions.set(new NamedFlag("UNREAD"), true);
- else if (term.parsed.down() == _("unread"))
+ else if (term.parsed == SEARCH_OP_VALUE_UNREAD)
removal_conditions.set(new NamedFlag("UNREAD"), false);
- else if (term.parsed.down() == _("starred"))
+ else if (term.parsed == SEARCH_OP_VALUE_STARRED)
removal_conditions.set(new NamedFlag("FLAGGED"), false);
return removal_conditions;
}
return removal_conditions;
}
-
+
private async void remove_results(ImapDB.SearchQuery query,
Gee.Map<ImapDB.EmailIdentifier, Gee.Set<string>> search_results,
Gee.Map<Geary.NamedFlag, bool> removal_conditions, Cancellable? cancellable = null) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]