Commit 149ed356 authored by David Champion's avatar David Champion

Abstract the SPAM_LIST as a generic REPLACE_LIST

REPLACE_LIST can be used more generally as a list of pattern
match-replace settings.  SPAM_LIST was a special case of this, so
spam handling has been been changed to use REPLACE_LIST instead, and
SPAM_LIST was removed.

A generic function for performing a REPLACE_LIST replacement has
been added in mutt_apply_replace().

Commited by Kevin McCarthy with some buffer overflow fixes in
mutt_apply_replace().
parent 5e3ac08d
......@@ -182,7 +182,7 @@ WHERE RX_LIST *MailLists INITVAL(0);
WHERE RX_LIST *UnMailLists INITVAL(0);
WHERE RX_LIST *SubscribedLists INITVAL(0);
WHERE RX_LIST *UnSubscribedLists INITVAL(0);
WHERE SPAM_LIST *SpamList INITVAL(0);
WHERE REPLACE_LIST *SpamList INITVAL(0);
WHERE RX_LIST *NoSpamList INITVAL(0);
......
......@@ -1160,7 +1160,7 @@ mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
unsigned int intval;
} digest;
struct md5_ctx ctx;
SPAM_LIST *spam;
REPLACE_LIST *spam;
RX_LIST *nospam;
hcachever = HCACHEVER;
......
......@@ -453,11 +453,11 @@ int mutt_add_to_rx_list (RX_LIST **list, const char *s, int flags, BUFFER *err)
return 0;
}
static int remove_from_spam_list (SPAM_LIST **list, const char *pat);
static int remove_from_replace_list (REPLACE_LIST **list, const char *pat);
static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *templ, BUFFER *err)
static int add_to_replace_list (REPLACE_LIST **list, const char *pat, const char *templ, BUFFER *err)
{
SPAM_LIST *t = NULL, *last = NULL;
REPLACE_LIST *t = NULL, *last = NULL;
REGEXP *rx;
int n;
const char *p;
......@@ -490,12 +490,12 @@ static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *temp
break;
}
/* If t is set, it's pointing into an extant SPAM_LIST* that we want to
/* If t is set, it's pointing into an extant REPLACE_LIST* that we want to
* update. Otherwise we want to make a new one to link at the list's end.
*/
if (!t)
{
t = mutt_new_spam_list();
t = mutt_new_replace_list();
t->rx = rx;
if (last)
last->next = t;
......@@ -503,7 +503,7 @@ static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *temp
*list = t;
}
/* Now t is the SPAM_LIST* that we want to modify. It is prepared. */
/* Now t is the REPLACE_LIST* that we want to modify. It is prepared. */
t->template = safe_strdup(templ);
/* Find highest match number in template string */
......@@ -524,9 +524,9 @@ static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *temp
if (t->nmatch > t->rx->rx->re_nsub)
{
snprintf (err->data, err->dsize, _("Not enough subexpressions for spam "
snprintf (err->data, err->dsize, _("Not enough subexpressions for "
"template"));
remove_from_spam_list(list, pat);
remove_from_replace_list(list, pat);
return -1;
}
......@@ -535,38 +535,38 @@ static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *temp
return 0;
}
static int remove_from_spam_list (SPAM_LIST **list, const char *pat)
static int remove_from_replace_list (REPLACE_LIST **list, const char *pat)
{
SPAM_LIST *spam, *prev;
REPLACE_LIST *cur, *prev;
int nremoved = 0;
/* Being first is a special case. */
spam = *list;
if (!spam)
cur = *list;
if (!cur)
return 0;
if (spam->rx && !mutt_strcmp(spam->rx->pattern, pat))
if (cur->rx && !mutt_strcmp(cur->rx->pattern, pat))
{
*list = spam->next;
mutt_free_regexp(&spam->rx);
FREE(&spam->template);
FREE(&spam);
*list = cur->next;
mutt_free_regexp(&cur->rx);
FREE(&cur->template);
FREE(&cur);
return 1;
}
prev = spam;
for (spam = prev->next; spam;)
prev = cur;
for (cur = prev->next; cur;)
{
if (!mutt_strcmp(spam->rx->pattern, pat))
if (!mutt_strcmp(cur->rx->pattern, pat))
{
prev->next = spam->next;
mutt_free_regexp(&spam->rx);
FREE(&spam->template);
FREE(&spam);
spam = prev->next;
prev->next = cur->next;
mutt_free_regexp(&cur->rx);
FREE(&cur->template);
FREE(&cur);
cur = prev->next;
++nremoved;
}
else
spam = spam->next;
cur = cur->next;
}
return nremoved;
......@@ -785,7 +785,7 @@ static int parse_spam_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *
mutt_extract_token (&templ, s, 0);
/* Add to the spam list. */
if (add_to_spam_list (&SpamList, buf->data, templ.data, err) != 0) {
if (add_to_replace_list (&SpamList, buf->data, templ.data, err) != 0) {
FREE(&templ.data);
return -1;
}
......@@ -809,13 +809,13 @@ static int parse_spam_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *
/* "*" is a special case. */
if (!mutt_strcmp(buf->data, "*"))
{
mutt_free_spam_list (&SpamList);
mutt_free_replace_list (&SpamList);
mutt_free_rx_list (&NoSpamList);
return 0;
}
/* If it's on the spam list, just remove it. */
if (remove_from_spam_list(&SpamList, buf->data) != 0)
if (remove_from_replace_list(&SpamList, buf->data) != 0)
return 0;
/* Otherwise, add it to the nospam list. */
......
......@@ -569,20 +569,20 @@ typedef struct rx_list_t
struct rx_list_t *next;
} RX_LIST;
typedef struct spam_list_t
typedef struct replace_list_t
{
REGEXP *rx;
int nmatch;
char *template;
struct spam_list_t *next;
} SPAM_LIST;
struct replace_list_t *next;
} REPLACE_LIST;
#define mutt_new_list() safe_calloc (1, sizeof (LIST))
#define mutt_new_rx_list() safe_calloc (1, sizeof (RX_LIST))
#define mutt_new_spam_list() safe_calloc (1, sizeof (SPAM_LIST))
#define mutt_new_replace_list() safe_calloc (1, sizeof (REPLACE_LIST))
void mutt_free_list (LIST **);
void mutt_free_rx_list (RX_LIST **);
void mutt_free_spam_list (SPAM_LIST **);
void mutt_free_replace_list (REPLACE_LIST **);
LIST *mutt_copy_list (LIST *);
int mutt_matches_ignore (const char *, LIST *);
......
......@@ -1074,6 +1074,98 @@ void mutt_safe_path (char *s, size_t l, ADDRESS *a)
*p = '_';
}
/* Note this function uses a fixed size buffer of LONG_STRING and so
* should only be used for visual modifications, such as disp_subj. */
char *mutt_apply_replace (char *dbuf, size_t dlen, char *sbuf, REPLACE_LIST *rlist)
{
REPLACE_LIST *l;
static regmatch_t *pmatch = NULL;
static int nmatch = 0;
static char twinbuf[2][LONG_STRING];
int switcher = 0;
char *p;
int i, n;
size_t cpysize, tlen;
char *src, *dst;
if (dbuf && dlen)
dbuf[0] = '\0';
if (sbuf == NULL || *sbuf == '\0' || (dbuf && !dlen))
return dbuf;
twinbuf[0][0] = '\0';
twinbuf[1][0] = '\0';
src = twinbuf[switcher];
dst = src;
strfcpy(src, sbuf, LONG_STRING);
for (l = rlist; l; l = l->next)
{
/* If this pattern needs more matches, expand pmatch. */
if (l->nmatch > nmatch)
{
safe_realloc (&pmatch, l->nmatch * sizeof(regmatch_t));
nmatch = l->nmatch;
}
if (regexec (l->rx->rx, src, l->nmatch, pmatch, 0) == 0)
{
tlen = 0;
switcher ^= 1;
dst = twinbuf[switcher];
dprint (5, (debugfile, "mutt_apply_replace: %s matches %s\n", src, l->rx->pattern));
/* Copy into other twinbuf with substitutions */
if (l->template)
{
for (p = l->template; *p && (tlen < LONG_STRING - 1); )
{
if (*p == '%')
{
p++;
if (*p == 'L')
{
p++;
cpysize = MIN (pmatch[0].rm_so, LONG_STRING - tlen - 1);
strncpy(&dst[tlen], src, cpysize);
tlen += cpysize;
}
else if (*p == 'R')
{
p++;
cpysize = MIN (strlen (src) - pmatch[0].rm_eo, LONG_STRING - tlen - 1);
strncpy(&dst[tlen], &src[pmatch[0].rm_eo], cpysize);
tlen += cpysize;
}
else
{
n = strtoul(p, &p, 10); /* get subst number */
while (isdigit((unsigned char)*p)) /* skip subst token */
++p;
for (i = pmatch[n].rm_so; (i < pmatch[n].rm_eo) && (tlen < LONG_STRING-1); i++)
dst[tlen++] = src[i];
}
}
else
dst[tlen++] = *p++;
}
}
dst[tlen] = '\0';
dprint (5, (debugfile, "mutt_apply_replace: subst %s\n", dst));
}
src = dst;
}
if (dbuf)
strfcpy(dbuf, dst, dlen);
else
dbuf = safe_strdup(dst);
return dbuf;
}
void mutt_FormatString (char *dest, /* output buffer */
size_t destlen, /* output buffer len */
......@@ -1888,9 +1980,9 @@ void mutt_free_rx_list (RX_LIST **list)
}
}
void mutt_free_spam_list (SPAM_LIST **list)
void mutt_free_replace_list (REPLACE_LIST **list)
{
SPAM_LIST *p;
REPLACE_LIST *p;
if (!list) return;
while (*list)
......@@ -1926,7 +2018,7 @@ int mutt_match_rx_list (const char *s, RX_LIST *l)
*
* Returns 1 if the argument `s` matches a pattern in the spam list, otherwise
* 0. */
int mutt_match_spam_list (const char *s, SPAM_LIST *l, char *text, int textsize)
int mutt_match_spam_list (const char *s, REPLACE_LIST *l, char *text, int textsize)
{
static regmatch_t *pmatch = NULL;
static int nmatch = 0;
......
......@@ -271,6 +271,7 @@ void mutt_alias_add_reverse (ALIAS *t);
void mutt_alias_delete_reverse (ALIAS *t);
int mutt_alloc_color (int fg, int bg);
int mutt_any_key_to_continue (const char *);
char *mutt_apply_replace (char *, size_t, char *, REPLACE_LIST *);
int mutt_buffy_check (int);
int mutt_buffy_notify (void);
int mutt_builtin_editor (const char *, HEADER *, HEADER *);
......@@ -324,7 +325,7 @@ int mutt_is_valid_mailbox (const char *);
int mutt_link_threads (HEADER *, HEADER *, CONTEXT *);
int mutt_lookup_mime_type (BODY *, const char *);
int mutt_match_rx_list (const char *, RX_LIST *);
int mutt_match_spam_list (const char *, SPAM_LIST *, char *, int);
int mutt_match_spam_list (const char *, REPLACE_LIST *, char *, int);
int mutt_messages_in_thread (CONTEXT *, HEADER *, int);
int mutt_multi_choice (char *prompt, char *letters);
int mutt_needs_mailcap (BODY *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment