[evolution-data-server] Bug 768258 - Decode headers before passing to regex comparison
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 768258 - Decode headers before passing to regex comparison
- Date: Fri, 1 Jul 2016 08:47:56 +0000 (UTC)
commit dcdf58b094b0028adbd5e0c1fe7c81f7bc7227db
Author: Milan Crha <mcrha redhat com>
Date: Fri Jul 1 10:45:51 2016 +0200
Bug 768258 - Decode headers before passing to regex comparison
camel/camel-filter-search.c | 41 ++---------
camel/camel-folder-search.c | 90 ++----------------------
camel/camel-search-private.c | 157 ++++++++++++++++++++++++++++++++++++++++++
camel/camel-search-private.h | 9 +++
4 files changed, 181 insertions(+), 116 deletions(-)
---
diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c
index 8b436f9..06173ad 100644
--- a/camel/camel-filter-search.c
+++ b/camel/camel-filter-search.c
@@ -259,8 +259,7 @@ check_header (struct _CamelSExp *f,
message = camel_filter_search_get_message (fms, f);
mime_part = CAMEL_MIME_PART (message);
- /* FIXME: what about Resent-To, Resent-Cc and Resent-From? */
- if (g_ascii_strcasecmp ("to", name) == 0 || g_ascii_strcasecmp ("cc", name) == 0 ||
g_ascii_strcasecmp ("from", name) == 0)
+ if (camel_search_header_is_address (name))
type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
else if (message) {
ct = camel_mime_part_get_content_type (mime_part);
@@ -375,47 +374,23 @@ header_regex (struct _CamelSExp *f,
CamelSExpResult *r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
CamelMimeMessage *message;
regex_t pattern;
- const gchar *contents;
+ gchar *contents = NULL;
message = camel_filter_search_get_message (fms, f);
if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING
- && (contents = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string))
+ && (contents = camel_search_get_header_decoded (argv[0]->value.string,
+ camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string),
+ camel_search_get_default_charset_from_message (message)))
&& camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | CAMEL_SEARCH_MATCH_ICASE,
argc - 1, argv + 1, fms->error) == 0) {
r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0;
regfree (&pattern);
} else
r->value.boolean = FALSE;
- return r;
-}
-
-static gchar *
-get_full_header (CamelMimeMessage *message)
-{
- CamelMimePart *mime_part;
- GString *str = g_string_new ("");
- gchar *ret;
- struct _camel_header_raw *h;
-
- mime_part = CAMEL_MIME_PART (message);
-
- for (h = mime_part->headers; h; h = h->next) {
- if (h->value != NULL) {
- g_string_append (str, h->name);
- if (isspace (h->value[0]))
- g_string_append (str, ":");
- else
- g_string_append (str, ": ");
- g_string_append (str, h->value);
- g_string_append_c (str, '\n');
- }
- }
+ g_free (contents);
- ret = str->str;
- g_string_free (str, FALSE);
-
- return ret;
+ return r;
}
static CamelSExpResult *
@@ -432,7 +407,7 @@ header_full_regex (struct _CamelSExp *f,
if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | CAMEL_SEARCH_MATCH_ICASE |
CAMEL_SEARCH_MATCH_NEWLINE,
argc, argv, fms->error) == 0) {
message = camel_filter_search_get_message (fms, f);
- contents = get_full_header (message);
+ contents = camel_search_get_all_headers_decoded (message);
r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0;
g_free (contents);
regfree (&pattern);
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c
index 6cfe5d1..abf4a34 100644
--- a/camel/camel-folder-search.c
+++ b/camel/camel-folder-search.c
@@ -625,76 +625,6 @@ match_words_messages (CamelFolderSearch *search,
return matches;
}
-static const gchar *
-get_default_charset (CamelMimeMessage *msg)
-{
- CamelContentType *ct;
- const gchar *charset;
-
- g_return_val_if_fail (msg != NULL, NULL);
-
- ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (msg));
- charset = camel_content_type_param (ct, "charset");
- if (!charset)
- charset = "utf-8";
-
- charset = camel_iconv_charset_name (charset);
-
- return charset;
-}
-
-static gchar *
-get_header_decoded (const gchar *header_value,
- const gchar *default_charset)
-{
- gchar *unfold, *decoded;
-
- if (!header_value || !*header_value)
- return NULL;
-
- unfold = camel_header_unfold (header_value);
- decoded = camel_header_decode_string (unfold, default_charset);
- g_free (unfold);
-
- return decoded;
-}
-
-static gchar *
-get_full_header (CamelMimeMessage *message,
- const gchar *default_charset)
-{
- CamelMimePart *mp = CAMEL_MIME_PART (message);
- GString *str = g_string_new ("");
- struct _camel_header_raw *h;
-
- for (h = mp->headers; h; h = h->next) {
- if (h->value != NULL) {
- g_string_append (str, h->name);
- if (isspace (h->value[0]))
- g_string_append (str, ":");
- else
- g_string_append (str, ": ");
- if (g_ascii_strcasecmp (h->name, "From") == 0 ||
- g_ascii_strcasecmp (h->name, "To") == 0 ||
- g_ascii_strcasecmp (h->name, "CC") == 0 ||
- g_ascii_strcasecmp (h->name, "BCC") == 0 ||
- g_ascii_strcasecmp (h->name, "Subject") == 0) {
- gchar *decoded = get_header_decoded (h->value, default_charset);
- if (decoded)
- g_string_append (str, decoded);
- else
- g_string_append (str, h->value);
- g_free (decoded);
- } else {
- g_string_append (str, h->value);
- }
- g_string_append_c (str, '\n');
- }
- }
-
- return g_string_free (str, FALSE);
-}
-
static gint
read_uid_callback (gpointer ref,
gint ncol,
@@ -1342,18 +1272,12 @@ folder_search_header_regex (CamelSExp *sexp,
CAMEL_SEARCH_MATCH_ICASE,
argc - 1, argv + 1,
search->priv->error) == 0) {
- gchar *decoded = NULL;
- const gchar *hader_name = argv[0]->value.string;
-
- if (g_ascii_strcasecmp (hader_name, "From") == 0 ||
- g_ascii_strcasecmp (hader_name, "To") == 0 ||
- g_ascii_strcasecmp (hader_name, "CC") == 0 ||
- g_ascii_strcasecmp (hader_name, "BCC") == 0 ||
- g_ascii_strcasecmp (hader_name, "Subject") == 0) {
- decoded = get_header_decoded (contents, get_default_charset (msg));
- if (decoded)
- contents = decoded;
- }
+ gchar *decoded;
+ const gchar *header_name = argv[0]->value.string;
+
+ decoded = camel_search_get_header_decoded (header_name, contents,
camel_search_get_default_charset_from_message (msg));
+ if (decoded)
+ contents = decoded;
r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0;
regfree (&pattern);
@@ -1396,7 +1320,7 @@ folder_search_header_full_regex (CamelSExp *sexp,
search->priv->error) == 0) {
gchar *contents;
- contents = get_full_header (msg, get_default_charset (msg));
+ contents = camel_search_get_all_headers_decoded (msg);
r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0;
g_free (contents);
diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c
index 0126ef3..d68d86f 100644
--- a/camel/camel-search-private.c
+++ b/camel/camel-search-private.c
@@ -717,3 +717,160 @@ camel_search_words_free (struct _camel_search_words *words)
g_free (words);
}
+/**
+ * camel_search_header_is_address:
+ * @header_name: A header name, like "Subject"
+ *
+ * Returns: Whether the @header_name is a header with a mail address
+ *
+ * Since: 3.22
+ **/
+gboolean
+camel_search_header_is_address (const gchar *header_name)
+{
+ const gchar *headers[] = {
+ "Reply-To",
+ "From",
+ "To",
+ "Cc",
+ "Bcc",
+ "Resent-From",
+ "Resent-To",
+ "Resent-Cc",
+ "Resent-Bcc",
+ NULL };
+ gint ii;
+
+ if (!header_name || !*header_name)
+ return FALSE;
+
+ for (ii = 0; headers[ii]; ii++) {
+ if (g_ascii_strcasecmp (headers[ii], header_name) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * camel_search_get_default_charset_from_message:
+ * @message: a #CamelMimeMessage
+ *
+ * Returns: Default charset of the @message; if none cannot be determined,
+ * UTF-8 is returned.
+ *
+ * Since: 3.22
+ **/
+const gchar *
+camel_search_get_default_charset_from_message (CamelMimeMessage *message)
+{
+ CamelContentType *ct;
+ const gchar *charset;
+
+ g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+ ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
+ charset = camel_content_type_param (ct, "charset");
+ if (!charset)
+ charset = "utf-8";
+
+ charset = camel_iconv_charset_name (charset);
+
+ return charset;
+}
+
+/**
+ * camel_search_get_header_decoded:
+ * @header_name: the header name
+ * @header_value: the header value
+ * @default_charset: (nullable): the default charset to use for the decode, or %NULL
+ *
+ * Decodes @header_value, if needed, either from an address header
+ * or the Subject header. Other @header_name headers are returned
+ * as is.
+ *
+ * Returns: (transfer full): decoded header value, suitable for text comparison.
+ * Free the returned pointer with g_free() when done with it.
+ *
+ * Since: 3.22
+ **/
+gchar *
+camel_search_get_header_decoded (const gchar *header_name,
+ const gchar *header_value,
+ const gchar *default_charset)
+{
+ gchar *unfold, *decoded;
+
+ if (!header_value || !*header_value)
+ return NULL;
+
+ unfold = camel_header_unfold (header_value);
+
+ if (g_ascii_strcasecmp (header_name, "Subject") == 0 ||
+ camel_search_header_is_address (header_name)) {
+ decoded = camel_header_decode_string (unfold, default_charset);
+ } else {
+ decoded = unfold;
+ unfold = NULL;
+ }
+
+ g_free (unfold);
+
+ return decoded;
+}
+
+/**
+ * camel_search_get_all_headers_decoded:
+ * @message: a #CamelMessage
+ *
+ * Returns: (transfer full): All headers of the @message, decoded where needed.
+ * Free the returned pointer with g_free() when done with it.
+ *
+ * Since: 3.22
+ **/
+gchar *
+camel_search_get_all_headers_decoded (CamelMimeMessage *message)
+{
+ CamelMedium *medium;
+ GString *str;
+ GArray *headers;
+ const gchar *default_charset;
+ guint ii;
+
+ g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+ medium = CAMEL_MEDIUM (message);
+ headers = camel_medium_get_headers (medium);
+ if (!headers)
+ return NULL;
+
+ default_charset = camel_search_get_default_charset_from_message (message);
+ str = g_string_new ("");
+
+ for (ii = 0; ii < headers->len; ii++) {
+ CamelMediumHeader *header;
+ gchar *content;
+
+ header = &g_array_index (headers, CamelMediumHeader, ii);
+ if (!header->value)
+ continue;
+
+ content = camel_search_get_header_decoded (header->name, header->value, default_charset);
+ if (!content)
+ continue;
+
+ g_string_append (str, header->name);
+ if (isspace (content[0]))
+ g_string_append (str, ":");
+ else
+ g_string_append (str, ": ");
+ g_string_append (str, content);
+ g_string_append_c (str, '\n');
+
+ g_free (content);
+ }
+
+ camel_medium_free_headers (medium, headers);
+
+ return g_string_free (str, FALSE);
+}
diff --git a/camel/camel-search-private.h b/camel/camel-search-private.h
index 5256b6c..5fee6f7 100644
--- a/camel/camel-search-private.h
+++ b/camel/camel-search-private.h
@@ -100,6 +100,15 @@ struct _camel_search_words *
camel_search_words_simple (struct _camel_search_words *words);
void camel_search_words_free (struct _camel_search_words *words);
+gboolean camel_search_header_is_address (const gchar *header_name);
+const gchar * camel_search_get_default_charset_from_message
+ (CamelMimeMessage *message);
+gchar * camel_search_get_header_decoded (const gchar *header_name,
+ const gchar *header_value,
+ const gchar *default_charset);
+gchar * camel_search_get_all_headers_decoded
+ (CamelMimeMessage *message);
+
G_END_DECLS
#endif /* CAMEL_SEARCH_PRIVATE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]