From: Colin Leroy Date: Tue, 25 Jan 2011 17:05:50 +0000 (+0000) Subject: 2011-01-25 [colin] 3.7.8cvs47 X-Git-Tag: REL_3_7_9~32 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=4e7adaef1e4cd08d245a105bdca1a89cd811792e 2011-01-25 [colin] 3.7.8cvs47 * src/matcher.c Fix matcher body parsing: decode mails with our MIME parser. This speeds up body search a bit as binary attachments are not searched anymore, slows down a bit full message searches, but not awfully. * src/summary_search.c Use matcher API to search, in all cases (advanced search or not). Also, fix little logic bugs related to combos history * src/common/utils.c * src/common/utils.h * src/procmime.c * src/procmime.h Remove dead code, export functions needed by matcher.c --- diff --git a/ChangeLog b/ChangeLog index 2a232cca4..872123a41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-01-25 [colin] 3.7.8cvs47 + + * src/matcher.c + Fix matcher body parsing: decode mails with our + MIME parser. This speeds up body search a bit as + binary attachments are not searched anymore, slows + down a bit full message searches, but not awfully. + * src/summary_search.c + Use matcher API to search, in all cases (advanced search or + not). Also, fix little logic bugs related to combos history + * src/common/utils.c + * src/common/utils.h + * src/procmime.c + * src/procmime.h + Remove dead code, export functions needed by matcher.c + 2011-01-25 [colin] 3.7.8cvs46 * src/compose.c diff --git a/PATCHSETS b/PATCHSETS index 1e4fe4385..8afdcfc3b 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -4120,3 +4120,4 @@ ( cvs diff -u -r 1.1.2.16 -r 1.1.2.17 manual/es/advanced.xml; ) > 3.7.8cvs44.patchset ( cvs diff -u -r 1.56.2.66 -r 1.56.2.67 src/pop.c; ) > 3.7.8cvs45.patchset ( cvs diff -u -r 1.382.2.566 -r 1.382.2.567 src/compose.c; cvs diff -u -r 1.204.2.199 -r 1.204.2.200 src/prefs_common.c; cvs diff -u -r 1.2.2.9 -r 1.2.2.10 src/common/md5.c; cvs diff -u -r 1.4.2.36 -r 1.4.2.37 src/common/ssl_certificate.c; ) > 3.7.8cvs46.patchset +( cvs diff -u -r 1.75.2.67 -r 1.75.2.68 src/matcher.c; cvs diff -u -r 1.49.2.137 -r 1.49.2.138 src/procmime.c; cvs diff -u -r 1.17.2.24 -r 1.17.2.25 src/procmime.h; cvs diff -u -r 1.15.2.59 -r 1.15.2.60 src/summary_search.c; cvs diff -u -r 1.36.2.189 -r 1.36.2.190 src/common/utils.c; cvs diff -u -r 1.20.2.74 -r 1.20.2.75 src/common/utils.h; ) > 3.7.8cvs47.patchset diff --git a/configure.ac b/configure.ac index 2a166fded..3efd3237b 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ MINOR_VERSION=7 MICRO_VERSION=8 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=46 +EXTRA_VERSION=47 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/common/utils.c b/src/common/utils.c index 70cf95ca5..826724b43 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -301,16 +301,6 @@ void ptr_array_free_strings(GPtrArray *array) } } -gboolean str_find(const gchar *haystack, const gchar *needle) -{ - return strstr(haystack, needle) != NULL ? TRUE : FALSE; -} - -gboolean str_case_find(const gchar *haystack, const gchar *needle) -{ - return strcasestr(haystack, needle) != NULL ? TRUE : FALSE; -} - gint to_number(const gchar *nstr) { register const gchar *p; diff --git a/src/common/utils.h b/src/common/utils.h index 2bdc1fc83..50f8afb14 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -287,13 +287,6 @@ guint str_case_hash (gconstpointer key); void ptr_array_free_strings (GPtrArray *array); -typedef gboolean (*StrFindFunc) (const gchar *haystack, - const gchar *needle); - -gboolean str_find (const gchar *haystack, - const gchar *needle); -gboolean str_case_find (const gchar *haystack, - const gchar *needle); /* number-string conversion */ gint to_number (const gchar *nstr); gchar *itos_buf (gchar *nstr, diff --git a/src/matcher.c b/src/matcher.c index 5626e3d9f..4e64420e2 100644 --- a/src/matcher.c +++ b/src/matcher.c @@ -599,48 +599,19 @@ const gchar *debug_context) return FALSE; } -/* FIXME body search is a hack. */ -static gboolean matcherprop_string_decode_match(MatcherProp *prop, const gchar *str, - const gchar *debug_context) +static gboolean matcherprop_header_line_match(MatcherProp *prop, const gchar *hdr, + const gchar *str, const gchar *debug_context) { - gchar *utf = NULL; - gchar tmp[BUFFSIZE]; + gchar *line = NULL; gboolean res = FALSE; - if (str == NULL) + if (hdr == NULL || str == NULL) return FALSE; - /* we try to decode QP first, because it's faster than base64 */ - qp_decode_const(tmp, BUFFSIZE-1, str); - if (!g_utf8_validate(tmp, -1, NULL)) { - utf = conv_codeset_strdup - (tmp, conv_get_locale_charset_str_no_utf8(), - CS_INTERNAL); - res = matcherprop_string_match(prop, utf, debug_context); - g_free(utf); - } else { - res = matcherprop_string_match(prop, tmp, debug_context); - } - - if (res == FALSE && (strchr(prop->expr, '=') || strchr(prop->expr, '_') - || strchr(str, '=') || strchr(str, '_'))) { - /* if searching for something with an equal char, maybe - * we should try to match the non-decoded string. - * In case it was not qp-encoded. */ - if (!g_utf8_validate(str, -1, NULL)) { - utf = conv_codeset_strdup - (str, conv_get_locale_charset_str_no_utf8(), - CS_INTERNAL); - res = matcherprop_string_match(prop, utf, debug_context); - g_free(utf); - } else { - res = matcherprop_string_match(prop, str, debug_context); - } - } - - /* FIXME base64 decoding is too slow, especially since text can - * easily be handled as base64. Don't even try now. */ - + line = g_strdup_printf("%s %s", hdr, str); + res = matcherprop_string_match(prop, line, debug_context); + g_free(line); + return res; } @@ -1281,13 +1252,23 @@ static gboolean matcherprop_match_one_header(MatcherProp *matcher, } break; case MATCHCRITERIA_HEADERS_PART: - return matcherprop_string_match(matcher, buf, _("header line")); - case MATCHCRITERIA_NOT_HEADERS_PART: - return !matcherprop_string_match(matcher, buf, _("headers line")); case MATCHCRITERIA_MESSAGE: - return matcherprop_string_decode_match(matcher, buf, _("message line")); + header = procheader_parse_header(buf); + if (!header) + return FALSE; + result = matcherprop_header_line_match(matcher, + header->name, header->body, _("header line")); + procheader_header_free(header); + return result; + case MATCHCRITERIA_NOT_HEADERS_PART: case MATCHCRITERIA_NOT_MESSAGE: - return !matcherprop_string_decode_match(matcher, buf, _("message line")); + header = procheader_parse_header(buf); + if (!header) + return FALSE; + result = !matcherprop_header_line_match(matcher, + header->name, header->body, _("header line")); + procheader_header_free(header); + return result; case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK: case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK: { @@ -1491,28 +1472,6 @@ static gboolean matcherprop_criteria_body(const MatcherProp *matcher) } } -/*! - *\brief Check if a (line) string matches the criteria - * described by a matcher structure - * - *\param matcher Matcher structure - *\param line String - * - *\return gboolean TRUE if string matches criteria - */ -static gboolean matcherprop_match_line(MatcherProp *matcher, const gchar *line) -{ - switch (matcher->criteria) { - case MATCHCRITERIA_BODY_PART: - case MATCHCRITERIA_MESSAGE: - return matcherprop_string_decode_match(matcher, line, _("body line")); - case MATCHCRITERIA_NOT_BODY_PART: - case MATCHCRITERIA_NOT_MESSAGE: - return !matcherprop_string_decode_match(matcher, line, _("body line")); - } - return FALSE; -} - /*! *\brief Check if a line in a message file's body matches * the criteria @@ -1522,45 +1481,94 @@ static gboolean matcherprop_match_line(MatcherProp *matcher, const gchar *line) * *\return gboolean TRUE if succesful match */ -static gboolean matcherlist_match_body(MatcherList *matchers, FILE *fp) +static gboolean matcherlist_match_body(MatcherList *matchers, gboolean body_only, MsgInfo *info) { GSList *l; + MimeInfo *mimeinfo = NULL; + MimeInfo *partinfo = NULL; gchar buf[BUFFSIZE]; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) { - MatcherProp *matcher = (MatcherProp *) l->data; - - if (matcher->done) - continue; + gboolean first_text_found = FALSE; + FILE *outfp = NULL; - /* if the criteria is ~body_part or ~message, ZERO lines - * must NOT match for the rule to match. */ - if (matcher->criteria == MATCHCRITERIA_NOT_BODY_PART || - matcher->criteria == MATCHCRITERIA_NOT_MESSAGE) { - if (matcherprop_match_line(matcher, buf)) { - matcher->result = TRUE; - } else { - matcher->result = FALSE; - matcher->done = TRUE; - } - /* else, just one line has to match */ - } else if (matcherprop_criteria_body(matcher) || - matcherprop_criteria_message(matcher)) { - if (matcherprop_match_line(matcher, buf)) { - matcher->result = TRUE; - matcher->done = TRUE; + cm_return_val_if_fail(info != NULL, FALSE); + + mimeinfo = procmime_scan_message(info); + + /* Skip headers */ + partinfo = procmime_mimeinfo_next(mimeinfo); + + for (; partinfo != NULL; partinfo = procmime_mimeinfo_next(partinfo)) { + + if (partinfo->type != MIMETYPE_TEXT && body_only) + continue; + + if (partinfo->type == MIMETYPE_TEXT) { + first_text_found = TRUE; + outfp = procmime_get_text_content(partinfo); + } else + outfp = procmime_get_binary_content(partinfo); + + if (!outfp) { + procmime_mimeinfo_free_all(mimeinfo); + return FALSE; + } + + while (fgets(buf, sizeof(buf), outfp) != NULL) { + strretchomp(buf); + + for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) { + MatcherProp *matcher = (MatcherProp *) l->data; + + if (matcher->done) + continue; + + /* Don't scan non-text parts when looking in body, only + * when looking in whole message + */ + if (partinfo && partinfo->type != MIMETYPE_TEXT && + (matcher->criteria == MATCHCRITERIA_NOT_BODY_PART || + matcher->criteria == MATCHCRITERIA_BODY_PART)) + continue; + + /* if the criteria is ~body_part or ~message, ZERO lines + * must match for the rule to match. + */ + if (matcher->criteria == MATCHCRITERIA_NOT_BODY_PART || + matcher->criteria == MATCHCRITERIA_NOT_MESSAGE) { + if (matcherprop_string_match(matcher, buf, + _("body line"))) { + matcher->result = FALSE; + matcher->done = TRUE; + } else + matcher->result = TRUE; + /* else, just one line has to match */ + } else if (matcherprop_criteria_body(matcher) || + matcherprop_criteria_message(matcher)) { + if (matcherprop_string_match(matcher, buf, + _("body line"))) { + matcher->result = TRUE; + matcher->done = TRUE; + } } - } - /* if the matchers are OR'ed and the rule matched, - * no need to check the others. */ - if (matcher->result && matcher->done) { - if (!matchers->bool_and) - return TRUE; + /* if the matchers are OR'ed and the rule matched, + * no need to check the others. */ + if (matcher->result && matcher->done) { + if (!matchers->bool_and) { + procmime_mimeinfo_free_all(mimeinfo); + fclose(outfp); + return TRUE; + } + } } } + fclose(outfp); + + if (body_only && first_text_found) + break; } + procmime_mimeinfo_free_all(mimeinfo); + return FALSE; } @@ -1578,6 +1586,7 @@ static gboolean matcherlist_match_file(MatcherList *matchers, MsgInfo *info, { gboolean read_headers; gboolean read_body; + gboolean body_only; GSList *l; FILE *fp; gchar *file; @@ -1586,6 +1595,7 @@ static gboolean matcherlist_match_file(MatcherList *matchers, MsgInfo *info, read_headers = FALSE; read_body = FALSE; + body_only = TRUE; for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) { MatcherProp *matcher = (MatcherProp *) l->data; @@ -1596,6 +1606,7 @@ static gboolean matcherlist_match_file(MatcherList *matchers, MsgInfo *info, if (matcherprop_criteria_message(matcher)) { read_headers = TRUE; read_body = TRUE; + body_only = FALSE; } matcher->result = FALSE; matcher->done = FALSE; @@ -1625,7 +1636,7 @@ static gboolean matcherlist_match_file(MatcherList *matchers, MsgInfo *info, /* read the body */ if (read_body) { - matcherlist_match_body(matchers, fp); + matcherlist_match_body(matchers, body_only, info); } for (l = matchers->matchers; l != NULL; l = g_slist_next(l)) { diff --git a/src/procmime.c b/src/procmime.c index 7783f9977..36dae9b23 100644 --- a/src/procmime.c +++ b/src/procmime.c @@ -190,8 +190,8 @@ MimeInfo *procmime_scan_message(MsgInfo *msginfo) { gchar *filename; MimeInfo *mimeinfo; - START_TIMING(""); - filename = procmsg_get_message_file_path(msginfo); + + filename = procmsg_get_message_file_path(msginfo); if (!filename || !is_file_exist(filename)) { g_free(filename); return NULL; @@ -204,7 +204,6 @@ MimeInfo *procmime_scan_message(MsgInfo *msginfo) mimeinfo = procmime_scan_queue_file(filename); g_free(filename); - END_TIMING(); return mimeinfo; } @@ -672,7 +671,7 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo) return 0; } -static FILE *procmime_get_text_content(MimeInfo *mimeinfo) +FILE *procmime_get_text_content(MimeInfo *mimeinfo) { FILE *tmpfp, *outfp; const gchar *src_codeset; @@ -778,6 +777,38 @@ static FILE *procmime_get_text_content(MimeInfo *mimeinfo) return outfp; } +FILE *procmime_get_binary_content(MimeInfo *mimeinfo) +{ + FILE *outfp; + gchar *tmpfile; + + cm_return_val_if_fail(mimeinfo != NULL, NULL); + + if (!procmime_decode_content(mimeinfo)) + return NULL; + + tmpfile = procmime_get_tmp_file_name(mimeinfo); + if (tmpfile == NULL) + return NULL; + + if (procmime_get_part(tmpfile, mimeinfo) < 0) { + g_free(tmpfile); + return NULL; + } + + outfp = g_fopen(tmpfile, "rb"); + if (outfp == NULL) { + g_unlink(tmpfile); + g_free(tmpfile); + return NULL; + } + + g_unlink(tmpfile); + g_free(tmpfile); + + return outfp; +} + /* search the first text part of (multipart) MIME message, decode, convert it and output to outfp. */ FILE *procmime_get_first_text_content(MsgInfo *msginfo) @@ -785,8 +816,8 @@ FILE *procmime_get_first_text_content(MsgInfo *msginfo) FILE *outfp = NULL; MimeInfo *mimeinfo, *partinfo; gboolean empty_ok = FALSE, short_scan = TRUE; - START_TIMING(""); - cm_return_val_if_fail(msginfo != NULL, NULL); + + cm_return_val_if_fail(msginfo != NULL, NULL); /* first we try to short-scan (for speed), refusing empty parts */ scan_again: @@ -819,7 +850,6 @@ scan_again: goto scan_again; } procmime_mimeinfo_free_all(mimeinfo); - END_TIMING(); return outfp; } @@ -904,68 +934,6 @@ gboolean procmime_msginfo_is_encrypted(MsgInfo *msginfo) return result; } -static gboolean procmime_find_string_part(MimeInfo *mimeinfo, const gchar *filename, - const gchar *str, StrFindFunc find_func) -{ - FILE *outfp; - gchar buf[BUFFSIZE]; - - cm_return_val_if_fail(mimeinfo != NULL, FALSE); - cm_return_val_if_fail(mimeinfo->type == MIMETYPE_TEXT, FALSE); - cm_return_val_if_fail(str != NULL, FALSE); - cm_return_val_if_fail(find_func != NULL, FALSE); - - outfp = procmime_get_text_content(mimeinfo); - - if (!outfp) - return FALSE; - - while (fgets(buf, sizeof(buf), outfp) != NULL) { - strretchomp(buf); - if (find_func(buf, str)) { - fclose(outfp); - return TRUE; - } - } - - fclose(outfp); - - return FALSE; -} - -gboolean procmime_find_string(MsgInfo *msginfo, const gchar *str, - StrFindFunc find_func) -{ - MimeInfo *mimeinfo; - MimeInfo *partinfo; - gchar *filename; - gboolean found = FALSE; - - cm_return_val_if_fail(msginfo != NULL, FALSE); - cm_return_val_if_fail(str != NULL, FALSE); - cm_return_val_if_fail(find_func != NULL, FALSE); - - filename = procmsg_get_message_file(msginfo); - if (!filename) return FALSE; - mimeinfo = procmime_scan_message(msginfo); - - for (partinfo = mimeinfo; partinfo != NULL; - partinfo = procmime_mimeinfo_next(partinfo)) { - if (partinfo->type == MIMETYPE_TEXT) { - if (procmime_find_string_part - (partinfo, filename, str, find_func) == TRUE) { - found = TRUE; - break; - } - } - } - - procmime_mimeinfo_free_all(mimeinfo); - g_free(filename); - - return found; -} - gchar *procmime_get_tmp_file_name(MimeInfo *mimeinfo) { static guint32 id = 0; diff --git a/src/procmime.h b/src/procmime.h index 122a530de..67ce06145 100644 --- a/src/procmime.h +++ b/src/procmime.h @@ -205,10 +205,6 @@ FILE *procmime_get_first_text_content (MsgInfo *msginfo); FILE *procmime_get_first_encrypted_text_content (MsgInfo *msginfo); -gboolean procmime_find_string (MsgInfo *msginfo, - const gchar *str, - StrFindFunc find_func); - gchar *procmime_get_tmp_file_name (MimeInfo *mimeinfo); gchar *procmime_get_part_file_name (MimeInfo *mimeinfo); @@ -237,6 +233,8 @@ gint procmime_write_mimeinfo(MimeInfo *mimeinfo, FILE *fp); void procmime_mimeparser_register(MimeParser *mimeparser); void procmime_mimeparser_unregister(MimeParser *mimeparser); +FILE *procmime_get_text_content(MimeInfo *mimeinfo); +FILE *procmime_get_binary_content(MimeInfo *mimeinfo); #ifdef __cplusplus } diff --git a/src/summary_search.c b/src/summary_search.c index 82a2b58ba..aa325ceba 100644 --- a/src/summary_search.c +++ b/src/summary_search.c @@ -502,10 +502,10 @@ static void summary_search_execute(gboolean backward, gboolean search_all) gchar *from_str = NULL, *to_str = NULL, *subject_str = NULL; gchar *body_str = NULL; gchar *adv_condition = NULL; - StrFindFunc str_find_func = NULL; gboolean is_fast = TRUE; gint interval = 1000; gint i = 0; + GSList *matchers = NULL; if (summary_is_locked(summaryview)) { return; @@ -515,11 +515,11 @@ static void summary_search_execute(gboolean backward, gboolean search_all) adv_search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(search_window.adv_search_checkbtn)); + if (search_window.matcher_list != NULL) { + matcherlist_free(search_window.matcher_list); + search_window.matcher_list = NULL; + } if (adv_search) { - if (search_window.matcher_list != NULL) { - matcherlist_free(search_window.matcher_list); - search_window.matcher_list = NULL; - } adv_condition = gtk_combo_box_get_active_text(GTK_COMBO_BOX(search_window.adv_condition_entry)); if (!adv_condition) adv_condition = gtk_editable_get_chars( @@ -550,12 +550,6 @@ static void summary_search_execute(gboolean backward, gboolean search_all) case_sens = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(search_window.case_checkbtn)); - if (case_sens) { - str_find_func = str_find; - } else { - str_find_func = str_case_find; - } - from_str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(search_window.from_entry)); to_str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(search_window.to_entry)); subject_str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(search_window.subject_entry)); @@ -591,30 +585,51 @@ static void summary_search_execute(gboolean backward, gboolean search_all) } /* add to history */ - if (from_str[0] != '\0') + if (from_str[0] != '\0') { + MatcherProp *prop = matcherprop_new(MATCHCRITERIA_FROM, + NULL, case_sens ? MATCHTYPE_MATCH:MATCHTYPE_MATCHCASE, + from_str, 0); + matchers = g_slist_append(matchers, prop); combobox_unset_popdown_strings(GTK_COMBO_BOX(search_window.from_entry)); prefs_common.summary_search_from_history = add_history( prefs_common.summary_search_from_history, from_str); combobox_set_popdown_strings(GTK_COMBO_BOX(search_window.from_entry), prefs_common.summary_search_from_history); - if (to_str[0] != '\0') + } + if (to_str[0] != '\0') { + MatcherProp *prop = matcherprop_new(MATCHCRITERIA_TO, + NULL, case_sens ? MATCHTYPE_MATCH:MATCHTYPE_MATCHCASE, + to_str, 0); + matchers = g_slist_append(matchers, prop); combobox_unset_popdown_strings(GTK_COMBO_BOX(search_window.to_entry)); prefs_common.summary_search_to_history = add_history( prefs_common.summary_search_to_history, to_str); combobox_set_popdown_strings(GTK_COMBO_BOX(search_window.to_entry), prefs_common.summary_search_to_history); - if (subject_str[0] != '\0') + } + if (subject_str[0] != '\0') { + MatcherProp *prop = matcherprop_new(MATCHCRITERIA_SUBJECT, + NULL, case_sens ? MATCHTYPE_MATCH:MATCHTYPE_MATCHCASE, + subject_str, 0); + matchers = g_slist_append(matchers, prop); combobox_unset_popdown_strings(GTK_COMBO_BOX(search_window.subject_entry)); prefs_common.summary_search_subject_history = add_history( prefs_common.summary_search_subject_history, subject_str); combobox_set_popdown_strings(GTK_COMBO_BOX(search_window.subject_entry), prefs_common.summary_search_subject_history); - if (body_str[0] != '\0') + } + if (body_str[0] != '\0') { + MatcherProp *prop = matcherprop_new(MATCHCRITERIA_BODY_PART, + NULL, case_sens ? MATCHTYPE_MATCH:MATCHTYPE_MATCHCASE, + body_str, 0); + matchers = g_slist_append(matchers, prop); combobox_unset_popdown_strings(GTK_COMBO_BOX(search_window.body_entry)); prefs_common.summary_search_body_history = add_history( prefs_common.summary_search_body_history, body_str); combobox_set_popdown_strings(GTK_COMBO_BOX(search_window.body_entry), prefs_common.summary_search_body_history); + } + search_window.matcher_list = matcherlist_new(matchers, bool_and); } search_window.is_searching = TRUE; @@ -694,67 +709,7 @@ static void summary_search_execute(gboolean backward, gboolean search_all) msginfo = gtk_cmctree_node_get_row_data(ctree, node); body_matched = FALSE; - if (adv_search) { - matched = matcherlist_match(search_window.matcher_list, msginfo); - } else { - if (bool_and) { - matched = TRUE; - if (*from_str) { - if (!msginfo->from || - !str_find_func(msginfo->from, from_str)) { - matched = FALSE; - } - } - if (matched && *to_str) { - if (!msginfo->to || - !str_find_func(msginfo->to, to_str)) { - matched = FALSE; - } - } - if (matched && *subject_str) { - if (!msginfo->subject || - !str_find_func(msginfo->subject, subject_str)) { - matched = FALSE; - } - } - if (matched && *body_str) { - if (procmime_find_string(msginfo, body_str, - str_find_func)) { - body_matched = TRUE; - } else { - matched = FALSE; - } - } - if (matched && !*from_str && !*to_str && - !*subject_str && !*body_str) { - matched = FALSE; - } - } else { - matched = FALSE; - if (*from_str && msginfo->from) { - if (str_find_func(msginfo->from, from_str)) { - matched = TRUE; - } - } - if (!matched && *to_str && msginfo->to) { - if (str_find_func(msginfo->to, to_str)) { - matched = TRUE; - } - } - if (!matched && *subject_str && msginfo->subject) { - if (str_find_func(msginfo->subject, subject_str)) { - matched = TRUE; - } - } - if (!matched && *body_str) { - if (procmime_find_string(msginfo, body_str, - str_find_func)) { - matched = TRUE; - body_matched = TRUE; - } - } - } - } + matched = matcherlist_match(search_window.matcher_list, msginfo); if (matched) { if (search_all) {