X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=pattern.c;h=a606ab9d7cc6289e738d8055bd0546195bed126b;hp=f9c0e11e8b05bdaf24462a99c691d47bfd55bce3;hb=b0811fbd6a0e218c9c310a6ef4170e81540e6c22;hpb=6833ce8bdca2d64e14485118f2a4417b7e1cb1b1 diff --git a/pattern.c b/pattern.c index f9c0e11..a606ab9 100644 --- a/pattern.c +++ b/pattern.c @@ -1,26 +1,30 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2000 Michael R. Elkins , and others - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif #include "mutt.h" +#include "buffer.h" +#include "handler.h" +#include "enter.h" +#include "ascii.h" +#include "mx.h" #include "mapping.h" #include "keymap.h" -#include "mailbox.h" #include "copy.h" +#include "mime.h" + +#include "lib/mem.h" +#include "lib/intl.h" +#include "lib/str.h" #include #include @@ -31,67 +35,72 @@ #include "mutt_crypt.h" -static int eat_regexp (pattern_t *pat, BUFFER *, BUFFER *); -static int eat_date (pattern_t *pat, BUFFER *, BUFFER *); -static int eat_range (pattern_t *pat, BUFFER *, BUFFER *); +static int eat_regexp (pattern_t * pat, BUFFER *, BUFFER *); +static int eat_date (pattern_t * pat, BUFFER *, BUFFER *); +static int eat_range (pattern_t * pat, BUFFER *, BUFFER *); -struct pattern_flags -{ - int tag; /* character used to represent this op */ - int op; /* operation to perform */ +struct pattern_flags { + int tag; /* character used to represent this op */ + int op; /* operation to perform */ int class; int (*eat_arg) (pattern_t *, BUFFER *, BUFFER *); -} -Flags[] = -{ - { 'A', M_ALL, 0, NULL }, - { 'b', M_BODY, M_FULL_MSG, eat_regexp }, - { 'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp }, - { 'c', M_CC, 0, eat_regexp }, - { 'C', M_RECIPIENT, 0, eat_regexp }, - { 'd', M_DATE, 0, eat_date }, - { 'D', M_DELETED, 0, NULL }, - { 'e', M_SENDER, 0, eat_regexp }, - { 'E', M_EXPIRED, 0, NULL }, - { 'f', M_FROM, 0, eat_regexp }, - { 'F', M_FLAG, 0, NULL }, - { 'g', M_CRYPT_SIGN, 0, NULL }, - { 'G', M_CRYPT_ENCRYPT, 0, NULL }, - { 'h', M_HEADER, M_FULL_MSG, eat_regexp }, - { 'i', M_ID, 0, eat_regexp }, - { 'k', M_PGP_KEY, 0, NULL }, - { 'L', M_ADDRESS, 0, eat_regexp }, - { 'l', M_LIST, 0, NULL }, - { 'm', M_MESSAGE, 0, eat_range }, - { 'n', M_SCORE, 0, eat_range }, - { 'N', M_NEW, 0, NULL }, - { 'O', M_OLD, 0, NULL }, - { 'p', M_PERSONAL_RECIP, 0, NULL }, - { 'P', M_PERSONAL_FROM, 0, NULL }, - { 'Q', M_REPLIED, 0, NULL }, - { 'R', M_READ, 0, NULL }, - { 'r', M_DATE_RECEIVED, 0, eat_date }, - { 's', M_SUBJECT, 0, eat_regexp }, - { 'S', M_SUPERSEDED, 0, NULL }, - { 'T', M_TAG, 0, NULL }, - { 't', M_TO, 0, eat_regexp }, - { 'U', M_UNREAD, 0, NULL }, - { 'v', M_COLLAPSED, 0, NULL }, - { 'V', M_CRYPT_VERIFIED, 0, NULL }, +} Flags[] = { + { + 'A', M_ALL, 0, NULL}, { + 'b', M_BODY, M_FULL_MSG, eat_regexp}, { + 'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp}, { + 'c', M_CC, 0, eat_regexp}, { + 'C', M_RECIPIENT, 0, eat_regexp}, { + 'd', M_DATE, 0, eat_date}, { + 'D', M_DELETED, 0, NULL}, { + 'e', M_SENDER, 0, eat_regexp}, { + 'E', M_EXPIRED, 0, NULL}, { + 'f', M_FROM, 0, eat_regexp}, { + 'F', M_FLAG, 0, NULL}, { + 'g', M_CRYPT_SIGN, 0, NULL}, { + 'G', M_CRYPT_ENCRYPT, 0, NULL}, { + 'h', M_HEADER, M_FULL_MSG, eat_regexp}, { + 'H', M_HORMEL, 0, eat_regexp}, { + 'i', M_ID, 0, eat_regexp}, { + 'k', M_PGP_KEY, 0, NULL}, { + 'L', M_ADDRESS, 0, eat_regexp}, { + 'l', M_LIST, 0, NULL}, { + 'm', M_MESSAGE, 0, eat_range}, { + 'M', M_MULTIPART, 0, NULL}, { + 'n', M_SCORE, 0, eat_range}, { + 'N', M_NEW, 0, NULL}, { + 'O', M_OLD, 0, NULL}, { + 'p', M_PERSONAL_RECIP, 0, NULL}, { + 'P', M_PERSONAL_FROM, 0, NULL}, { + 'Q', M_REPLIED, 0, NULL}, { + 'R', M_READ, 0, NULL}, { + 'r', M_DATE_RECEIVED, 0, eat_date}, { + 's', M_SUBJECT, 0, eat_regexp}, { + 'S', M_SUPERSEDED, 0, NULL}, { + 'T', M_TAG, 0, NULL}, { + 't', M_TO, 0, eat_regexp}, { + 'U', M_UNREAD, 0, NULL}, { + 'u', M_SUBSCRIBED_LIST, 0, NULL}, { + 'v', M_COLLAPSED, 0, NULL}, { + 'V', M_CRYPT_VERIFIED, 0, NULL}, #ifdef USE_NNTP - { 'w', M_NEWSGROUPS, 0, eat_regexp }, + { + 'w', M_NEWSGROUPS, 0, eat_regexp}, #endif - { 'x', M_REFERENCE, 0, eat_regexp }, - { 'y', M_XLABEL, 0, eat_regexp }, - { 'z', M_SIZE, 0, eat_range }, - { '=', M_DUPLICATED, 0, NULL }, - { 0 } + { + 'x', M_REFERENCE, 0, eat_regexp}, { + 'y', M_XLABEL, 0, eat_regexp}, { + 'z', M_SIZE, 0, eat_range}, { + '=', M_DUPLICATED, 0, NULL}, { + '$', M_UNREFERENCED, 0, NULL}, { + '*', M_REALNAME, 0, NULL}, { + 0} }; static pattern_t *SearchPattern = NULL; /* current search pattern */ -static char LastSearch[STRING] = { 0 }; /* last pattern searched for */ -static char LastSearchExpn[LONG_STRING] = { 0 }; /* expanded version of - LastSearch */ +static char LastSearch[STRING] = { 0 }; /* last pattern searched for */ +static char LastSearchExpn[LONG_STRING] = { 0 }; /* expanded version of + LastSearch */ #define M_MAXRANGE -1 @@ -110,8 +119,7 @@ int mutt_getvaluebychar (char ch, struct mapping_t *table) { int i; - for (i = 0; table[i].name; i++) - { + for (i = 0; table[i].name; i++) { if (ch == table[i].name[0]) return table[i].value; } @@ -122,17 +130,17 @@ int mutt_getvaluebychar (char ch, struct mapping_t *table) /* if no uppercase letters are given, do a case-insensitive search */ int mutt_which_case (const char *s) { - while (*s) - { + while (*s) { if (isalpha ((unsigned char) *s) && isupper ((unsigned char) *s)) - return 0; /* case-sensitive */ + return 0; /* case-sensitive */ s++; } - return REG_ICASE; /* case-insensitive */ + return REG_ICASE; /* case-insensitive */ } static int -msg_search (CONTEXT *ctx, regex_t *rx, char *buf, size_t blen, int op, int msgno) +msg_search (CONTEXT * ctx, regex_t * rx, char *buf, size_t blen, int op, + int msgno) { char tempfile[_POSIX_PATH_MAX]; MESSAGE *msg = NULL; @@ -143,42 +151,36 @@ msg_search (CONTEXT *ctx, regex_t *rx, char *buf, size_t blen, int op, int msgno int match = 0; HEADER *h = ctx->hdrs[msgno]; - if ((msg = mx_open_message (ctx, msgno)) != NULL) - { - if (option (OPTTHOROUGHSRC)) - { + if ((msg = mx_open_message (ctx, msgno)) != NULL) { + if (option (OPTTHOROUGHSRC)) { /* decode the header / body */ memset (&s, 0, sizeof (s)); s.fpin = msg->fp; s.flags = M_CHARCONV; mutt_mktemp (tempfile); - if ((s.fpout = safe_fopen (tempfile, "w+")) == NULL) - { - mutt_perror (tempfile); - return (0); + if ((s.fpout = safe_fopen (tempfile, "w+")) == NULL) { + mutt_perror (tempfile); + return (0); } if (op != M_BODY) - mutt_copy_header (msg->fp, h, s.fpout, CH_FROM | CH_DECODE, NULL); - - if (op != M_HEADER) - { - mutt_parse_mime_message (ctx, h); - - if (WithCrypto && (h->security & ENCRYPT) - && !crypt_valid_passphrase(h->security)) - { - mx_close_message (&msg); - if (fp) - { - fclose (fp); - unlink (tempfile); - } - return (0); - } - - fseek (msg->fp, h->offset, 0); - mutt_body_handler (h->content, &s); + mutt_copy_header (msg->fp, h, s.fpout, CH_FROM | CH_DECODE, NULL); + + if (op != M_HEADER) { + mutt_parse_mime_message (ctx, h); + + if (WithCrypto && (h->security & ENCRYPT) + && !crypt_valid_passphrase (h->security)) { + mx_close_message (&msg); + if (fp) { + fclose (fp); + unlink (tempfile); + } + return (0); + } + + fseek (msg->fp, h->offset, 0); + mutt_body_handler (h->content, &s); } fp = s.fpout; @@ -187,40 +189,34 @@ msg_search (CONTEXT *ctx, regex_t *rx, char *buf, size_t blen, int op, int msgno fstat (fileno (fp), &st); lng = (long) st.st_size; } - else - { + else { /* raw header / body */ fp = msg->fp; - if (op != M_BODY) - { - fseek (fp, h->offset, 0); - lng = h->content->offset - h->offset; + if (op != M_BODY) { + fseek (fp, h->offset, 0); + lng = h->content->offset - h->offset; } - if (op != M_HEADER) - { - if (op == M_BODY) - fseek (fp, h->content->offset, 0); - lng += h->content->length; + if (op != M_HEADER) { + if (op == M_BODY) + fseek (fp, h->content->offset, 0); + lng += h->content->length; } } /* search the file "fp" */ - while (lng > 0) - { + while (lng > 0) { if (fgets (buf, blen - 1, fp) == NULL) - break; /* don't loop forever */ - if (regexec (rx, buf, 0, NULL, 0) == 0) - { - match = 1; - break; + break; /* don't loop forever */ + if (regexec (rx, buf, 0, NULL, 0) == 0) { + match = 1; + break; } - lng -= mutt_strlen (buf); + lng -= str_len (buf); } - + mx_close_message (&msg); - if (option (OPTTHOROUGHSRC)) - { + if (option (OPTTHOROUGHSRC)) { fclose (fp); unlink (tempfile); } @@ -229,75 +225,68 @@ msg_search (CONTEXT *ctx, regex_t *rx, char *buf, size_t blen, int op, int msgno return match; } -int eat_regexp (pattern_t *pat, BUFFER *s, BUFFER *err) +int eat_regexp (pattern_t * pat, BUFFER * s, BUFFER * err) { BUFFER buf; int r; memset (&buf, 0, sizeof (buf)); if (mutt_extract_token (&buf, s, M_TOKEN_PATTERN | M_TOKEN_COMMENT) != 0 || - !buf.data) - { + !buf.data) { snprintf (err->data, err->dsize, _("Error in expression: %s"), s->dptr); return (-1); } - pat->rx = safe_malloc (sizeof (regex_t)); - r = REGCOMP (pat->rx, buf.data, REG_NEWLINE | REG_NOSUB | mutt_which_case (buf.data)); - FREE (&buf.data); - if (r) - { + pat->rx = mem_malloc (sizeof (regex_t)); + r = + REGCOMP (pat->rx, buf.data, + REG_NEWLINE | REG_NOSUB | mutt_which_case (buf.data)); + mem_free (&buf.data); + if (r) { regerror (r, pat->rx, err->data, err->dsize); regfree (pat->rx); - FREE (&pat->rx); + mem_free (&pat->rx); return (-1); } return 0; } -int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) +int eat_range (pattern_t * pat, BUFFER * s, BUFFER * err) { char *tmp; int do_exclusive = 0; int skip_quote = 0; - + /* * If simple_search is set to "~m %s", the range will have double quotes * around it... */ - if (*s->dptr == '"') - { + if (*s->dptr == '"') { s->dptr++; skip_quote = 1; } if (*s->dptr == '<') do_exclusive = 1; - if ((*s->dptr != '-') && (*s->dptr != '<')) - { + if ((*s->dptr != '-') && (*s->dptr != '<')) { /* range minimum */ - if (*s->dptr == '>') - { + if (*s->dptr == '>') { pat->max = M_MAXRANGE; - pat->min = strtol (s->dptr + 1, &tmp, 0) + 1; /* exclusive range */ + pat->min = strtol (s->dptr + 1, &tmp, 0) + 1; /* exclusive range */ } else pat->min = strtol (s->dptr, &tmp, 0); - if (toupper ((unsigned char) *tmp) == 'K') /* is there a prefix? */ - { + if (toupper ((unsigned char) *tmp) == 'K') { /* is there a prefix? */ pat->min *= 1024; tmp++; } - else if (toupper ((unsigned char) *tmp) == 'M') - { + else if (toupper ((unsigned char) *tmp) == 'M') { pat->min *= 1048576; tmp++; } - if (*s->dptr == '>') - { + if (*s->dptr == '>') { s->dptr = tmp; return 0; } - if (*tmp != '-') - { + if (*tmp != '-') { /* exact value */ pat->max = pat->min; s->dptr = tmp; @@ -305,23 +294,19 @@ int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) } tmp++; } - else - { + else { s->dptr++; tmp = s->dptr; } - - if (isdigit ((unsigned char) *tmp)) - { + + if (isdigit ((unsigned char) *tmp)) { /* range maximum */ pat->max = strtol (tmp, &tmp, 0); - if (toupper ((unsigned char) *tmp) == 'K') - { + if (toupper ((unsigned char) *tmp) == 'K') { pat->max *= 1024; tmp++; } - else if (toupper ((unsigned char) *tmp) == 'M') - { + else if (toupper ((unsigned char) *tmp) == 'M') { pat->max *= 1048576; tmp++; } @@ -339,20 +324,18 @@ int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) return 0; } -static const char *getDate (const char *s, struct tm *t, BUFFER *err) +static const char *getDate (const char *s, struct tm *t, BUFFER * err) { char *p; time_t now = time (NULL); struct tm *tm = localtime (&now); t->tm_mday = strtol (s, &p, 10); - if (t->tm_mday < 1 || t->tm_mday > 31) - { + if (t->tm_mday < 1 || t->tm_mday > 31) { snprintf (err->data, err->dsize, _("Invalid day of month: %s"), s); return NULL; } - if (*p != '/') - { + if (*p != '/') { /* fill in today's month and year */ t->tm_mon = tm->tm_mon; t->tm_year = tm->tm_year; @@ -360,19 +343,17 @@ static const char *getDate (const char *s, struct tm *t, BUFFER *err) } p++; t->tm_mon = strtol (p, &p, 10) - 1; - if (t->tm_mon < 0 || t->tm_mon > 11) - { + if (t->tm_mon < 0 || t->tm_mon > 11) { snprintf (err->data, err->dsize, _("Invalid month: %s"), p); return NULL; } - if (*p != '/') - { + if (*p != '/') { t->tm_year = tm->tm_year; return p; } p++; t->tm_year = strtol (p, &p, 10); - if (t->tm_year < 70) /* year 2000+ */ + if (t->tm_year < 70) /* year 2000+ */ t->tm_year += 100; else if (t->tm_year > 1900) t->tm_year -= 1900; @@ -387,25 +368,25 @@ static const char *get_offset (struct tm *tm, const char *s, int sign) { char *ps; int offset = strtol (s, &ps, 0); + if ((sign < 0 && offset > 0) || (sign > 0 && offset < 0)) offset = -offset; - switch (*ps) - { - case 'y': - tm->tm_year += offset; - break; - case 'm': - tm->tm_mon += offset; - break; - case 'w': - tm->tm_mday += 7 * offset; - break; - case 'd': - tm->tm_mday += offset; - break; - default: - return s; + switch (*ps) { + case 'y': + tm->tm_year += offset; + break; + case 'm': + tm->tm_mon += offset; + break; + case 'w': + tm->tm_mday += 7 * offset; + break; + case 'd': + tm->tm_mday += offset; + break; + default: + return s; } mutt_normalize_time (tm); return (ps + 1); @@ -416,118 +397,109 @@ static void adjust_date_range (struct tm *min, struct tm *max) if (min->tm_year > max->tm_year || (min->tm_year == max->tm_year && min->tm_mon > max->tm_mon) || (min->tm_year == max->tm_year && min->tm_mon == max->tm_mon - && min->tm_mday > max->tm_mday)) - { + && min->tm_mday > max->tm_mday)) { int tmp; - + tmp = min->tm_year; min->tm_year = max->tm_year; max->tm_year = tmp; - + tmp = min->tm_mon; min->tm_mon = max->tm_mon; max->tm_mon = tmp; - + tmp = min->tm_mday; min->tm_mday = max->tm_mday; max->tm_mday = tmp; - + min->tm_hour = min->tm_min = min->tm_sec = 0; max->tm_hour = 23; max->tm_min = max->tm_sec = 59; } } -static const char * parse_date_range (const char* pc, struct tm *min, - struct tm *max, int haveMin, struct tm *baseMin, BUFFER *err) +static const char *parse_date_range (const char *pc, struct tm *min, + struct tm *max, int haveMin, + struct tm *baseMin, BUFFER * err) { - int flag = M_PDR_NONE; - while (*pc && ((flag & M_PDR_DONE) == 0)) - { + int flag = M_PDR_NONE; + + while (*pc && ((flag & M_PDR_DONE) == 0)) { const char *pt; char ch = *pc++; + SKIPWS (pc); - switch (ch) - { - case '-': + switch (ch) { + case '-': { - /* try a range of absolute date minus offset of Ndwmy */ - pt = get_offset (min, pc, -1); - if (pc == pt) - { - if (flag == M_PDR_NONE) - { /* nothing yet and no offset parsed => absolute date? */ - if (!getDate (pc, max, err)) - flag |= (M_PDR_ABSOLUTE | M_PDR_ERRORDONE); /* done bad */ - else - { - /* reestablish initial base minimum if not specified */ - if (!haveMin) - memcpy (min, baseMin, sizeof(struct tm)); - flag |= (M_PDR_ABSOLUTE | M_PDR_DONE); /* done good */ - } - } - else - flag |= M_PDR_ERRORDONE; - } - else - { - pc = pt; - if (flag == M_PDR_NONE && !haveMin) - { /* the very first "-3d" without a previous absolute date */ - max->tm_year = min->tm_year; - max->tm_mon = min->tm_mon; - max->tm_mday = min->tm_mday; - } - flag |= M_PDR_MINUS; - } + /* try a range of absolute date minus offset of Ndwmy */ + pt = get_offset (min, pc, -1); + if (pc == pt) { + if (flag == M_PDR_NONE) { /* nothing yet and no offset parsed => absolute date? */ + if (!getDate (pc, max, err)) + flag |= (M_PDR_ABSOLUTE | M_PDR_ERRORDONE); /* done bad */ + else { + /* reestablish initial base minimum if not specified */ + if (!haveMin) + memcpy (min, baseMin, sizeof (struct tm)); + flag |= (M_PDR_ABSOLUTE | M_PDR_DONE); /* done good */ + } + } + else + flag |= M_PDR_ERRORDONE; + } + else { + pc = pt; + if (flag == M_PDR_NONE && !haveMin) { /* the very first "-3d" without a previous absolute date */ + max->tm_year = min->tm_year; + max->tm_mon = min->tm_mon; + max->tm_mday = min->tm_mday; + } + flag |= M_PDR_MINUS; + } } break; - case '+': - { /* enlarge plusRange */ - pt = get_offset (max, pc, 1); - if (pc == pt) - flag |= M_PDR_ERRORDONE; - else - { - pc = pt; - flag |= M_PDR_PLUS; - } + case '+': + { /* enlarge plusRange */ + pt = get_offset (max, pc, 1); + if (pc == pt) + flag |= M_PDR_ERRORDONE; + else { + pc = pt; + flag |= M_PDR_PLUS; + } } break; - case '*': - { /* enlarge window in both directions */ - pt = get_offset (min, pc, -1); - if (pc == pt) - flag |= M_PDR_ERRORDONE; - else - { - pc = get_offset (max, pc, 1); - flag |= M_PDR_WINDOW; - } + case '*': + { /* enlarge window in both directions */ + pt = get_offset (min, pc, -1); + if (pc == pt) + flag |= M_PDR_ERRORDONE; + else { + pc = get_offset (max, pc, 1); + flag |= M_PDR_WINDOW; + } } break; - default: - flag |= M_PDR_ERRORDONE; + default: + flag |= M_PDR_ERRORDONE; } SKIPWS (pc); } - if ((flag & M_PDR_ERROR) && !(flag & M_PDR_ABSOLUTE)) - { /* getDate has its own error message, don't overwrite it here */ - snprintf (err->data, err->dsize, _("Invalid relative date: %s"), pc-1); + if ((flag & M_PDR_ERROR) && !(flag & M_PDR_ABSOLUTE)) { /* getDate has its own error message, don't overwrite it here */ + snprintf (err->data, err->dsize, _("Invalid relative date: %s"), pc - 1); } return ((flag & M_PDR_ERROR) ? NULL : pc); } -static int eat_date (pattern_t *pat, BUFFER *s, BUFFER *err) +static int eat_date (pattern_t * pat, BUFFER * s, BUFFER * err) { BUFFER buffer; struct tm min, max; memset (&buffer, 0, sizeof (buffer)); if (mutt_extract_token (&buffer, s, M_TOKEN_COMMENT | M_TOKEN_PATTERN) != 0 - || !buffer.data) - { + || !buffer.data) { strfcpy (err->data, _("error in expression"), err->dsize); return (-1); } @@ -551,28 +523,25 @@ static int eat_date (pattern_t *pat, BUFFER *s, BUFFER *err) max.tm_min = 59; max.tm_sec = 59; - if (strchr ("<>=", buffer.data[0])) - { + if (strchr ("<>=", buffer.data[0])) { /* offset from current time - <3d less than three days ago - >3d more than three days ago - =3d exactly three days ago */ + <3d less than three days ago + >3d more than three days ago + =3d exactly three days ago */ time_t now = time (NULL); struct tm *tm = localtime (&now); int exact = 0; - if (buffer.data[0] == '<') - { + if (buffer.data[0] == '<') { memcpy (&min, tm, sizeof (min)); tm = &min; } - else - { + else { memcpy (&max, tm, sizeof (max)); tm = &max; if (buffer.data[0] == '=') - exact++; + exact++; } tm->tm_hour = 23; tm->tm_min = tm->tm_sec = 59; @@ -580,61 +549,56 @@ static int eat_date (pattern_t *pat, BUFFER *s, BUFFER *err) /* force negative offset */ get_offset (tm, buffer.data + 1, -1); - if (exact) - { + if (exact) { /* start at the beginning of the day in question */ memcpy (&min, &max, sizeof (max)); min.tm_hour = min.tm_sec = min.tm_min = 0; } } - else - { + else { const char *pc = buffer.data; int haveMin = FALSE; int untilNow = FALSE; - if (isdigit ((unsigned char)*pc)) - { + + if (isdigit ((unsigned char) *pc)) { /* mininum date specified */ - if ((pc = getDate (pc, &min, err)) == NULL) - { - FREE (&buffer.data); - return (-1); + if ((pc = getDate (pc, &min, err)) == NULL) { + mem_free (&buffer.data); + return (-1); } haveMin = TRUE; SKIPWS (pc); - if (*pc == '-') - { + if (*pc == '-') { const char *pt = pc + 1; - SKIPWS (pt); - untilNow = (*pt == '\0'); + + SKIPWS (pt); + untilNow = (*pt == '\0'); } } - if (!untilNow) - { /* max date or relative range/window */ + if (!untilNow) { /* max date or relative range/window */ struct tm baseMin; - if (!haveMin) - { /* save base minimum and set current date, e.g. for "-3d+1d" */ - time_t now = time (NULL); - struct tm *tm = localtime (&now); - memcpy (&baseMin, &min, sizeof(baseMin)); - memcpy (&min, tm, sizeof (min)); - min.tm_hour = min.tm_sec = min.tm_min = 0; + if (!haveMin) { /* save base minimum and set current date, e.g. for "-3d+1d" */ + time_t now = time (NULL); + struct tm *tm = localtime (&now); + + memcpy (&baseMin, &min, sizeof (baseMin)); + memcpy (&min, tm, sizeof (min)); + min.tm_hour = min.tm_sec = min.tm_min = 0; } - + /* preset max date for relative offsets, - if nothing follows we search for messages on a specific day */ + if nothing follows we search for messages on a specific day */ max.tm_year = min.tm_year; max.tm_mon = min.tm_mon; max.tm_mday = min.tm_mday; - if (!parse_date_range (pc, &min, &max, haveMin, &baseMin, err)) - { /* bail out on any parsing error */ - FREE (&buffer.data); - return (-1); + if (!parse_date_range (pc, &min, &max, haveMin, &baseMin, err)) { /* bail out on any parsing error */ + mem_free (&buffer.data); + return (-1); } } } @@ -645,7 +609,7 @@ static int eat_date (pattern_t *pat, BUFFER *s, BUFFER *err) pat->min = mutt_mktime (&min, 1); pat->max = mutt_mktime (&max, 1); - FREE (&buffer.data); + mem_free (&buffer.data); return 0; } @@ -660,45 +624,41 @@ static struct pattern_flags *lookup_tag (char tag) return NULL; } -static /* const */ char *find_matching_paren (/* const */ char *s) +static /* const */ char *find_matching_paren ( /* const */ char *s) { int level = 1; - for (; *s; s++) - { + for (; *s; s++) { if (*s == '(') level++; - else if (*s == ')') - { + else if (*s == ')') { level--; if (!level) - break; + break; } } return s; } -void mutt_pattern_free (pattern_t **pat) +void mutt_pattern_free (pattern_t ** pat) { pattern_t *tmp; - while (*pat) - { + while (*pat) { tmp = *pat; *pat = (*pat)->next; - if (tmp->rx) - { + if (tmp->rx) { regfree (tmp->rx); - FREE (&tmp->rx); + mem_free (&tmp->rx); } if (tmp->child) mutt_pattern_free (&tmp->child); - FREE (&tmp); + mem_free (&tmp); } } -pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err) +pattern_t *mutt_pattern_comp ( /* const */ char *s, int flags, BUFFER * err) { pattern_t *curlist = NULL; pattern_t *tmp; @@ -706,7 +666,7 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err) int not = 0; int alladdr = 0; int or = 0; - int implicit = 1; /* used to detect logical AND operator */ + int implicit = 1; /* used to detect logical AND operator */ struct pattern_flags *entry; char *p; char *buf; @@ -714,146 +674,134 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err) memset (&ps, 0, sizeof (ps)); ps.dptr = s; - ps.dsize = mutt_strlen (s); + ps.dsize = str_len (s); - while (*ps.dptr) - { + while (*ps.dptr) { SKIPWS (ps.dptr); - switch (*ps.dptr) - { - case '^': - ps.dptr++; - alladdr = !alladdr; - break; - case '!': - ps.dptr++; - not = !not; - break; - case '|': - if (!or) - { - if (!curlist) - { - snprintf (err->data, err->dsize, _("error in pattern at: %s"), ps.dptr); - return NULL; - } - if (curlist->next) - { - /* A & B | C == (A & B) | C */ - tmp = new_pattern (); - tmp->op = M_AND; - tmp->child = curlist; - - curlist = tmp; - last = curlist; - } - - or = 1; - } - ps.dptr++; - implicit = 0; - not = 0; - alladdr = 0; - break; - case '~': - if (implicit && or) - { - /* A | B & C == (A | B) & C */ - tmp = new_pattern (); - tmp->op = M_OR; - tmp->child = curlist; - curlist = tmp; - last = tmp; - or = 0; - } - - tmp = new_pattern (); - tmp->not = not; - tmp->alladdr = alladdr; - not = 0; - alladdr=0; - - if (last) - last->next = tmp; - else - curlist = tmp; - last = tmp; - - ps.dptr++; /* move past the ~ */ - if ((entry = lookup_tag (*ps.dptr)) == NULL) - { - snprintf (err->data, err->dsize, _("%c: invalid command"), *ps.dptr); - mutt_pattern_free (&curlist); - return NULL; - } - if (entry->class && (flags & entry->class) == 0) - { - snprintf (err->data, err->dsize, _("%c: not supported in this mode"), *ps.dptr); - mutt_pattern_free (&curlist); - return NULL; - } - tmp->op = entry->op; - - ps.dptr++; /* eat the operator and any optional whitespace */ - SKIPWS (ps.dptr); - - if (entry->eat_arg) - { - if (!*ps.dptr) - { - snprintf (err->data, err->dsize, _("missing parameter")); - mutt_pattern_free (&curlist); - return NULL; - } - if (entry->eat_arg (tmp, &ps, err) == -1) - { - mutt_pattern_free (&curlist); - return NULL; - } - } - implicit = 1; - break; - case '(': - p = find_matching_paren (ps.dptr + 1); - if (*p != ')') - { - snprintf (err->data, err->dsize, _("mismatched parenthesis: %s"), ps.dptr); - mutt_pattern_free (&curlist); - return NULL; - } - /* compile the sub-expression */ - buf = mutt_substrdup (ps.dptr + 1, p); - if ((tmp = mutt_pattern_comp (buf, flags, err)) == NULL) - { - FREE (&buf); - mutt_pattern_free (&curlist); - return NULL; - } - FREE (&buf); - if (last) - last->next = tmp; - else - curlist = tmp; - last = tmp; - tmp->not ^= not; - tmp->alladdr |= alladdr; - not = 0; - alladdr = 0; - ps.dptr = p + 1; /* restore location */ - break; - default: - snprintf (err->data, err->dsize, _("error in pattern at: %s"), ps.dptr); - mutt_pattern_free (&curlist); - return NULL; + switch (*ps.dptr) { + case '^': + ps.dptr++; + alladdr = !alladdr; + break; + case '!': + ps.dptr++; + not = !not; + break; + case '|': + if (!or) { + if (!curlist) { + snprintf (err->data, err->dsize, _("error in pattern at: %s"), + ps.dptr); + return NULL; + } + if (curlist->next) { + /* A & B | C == (A & B) | C */ + tmp = new_pattern (); + tmp->op = M_AND; + tmp->child = curlist; + + curlist = tmp; + last = curlist; + } + + or = 1; + } + ps.dptr++; + implicit = 0; + not = 0; + alladdr = 0; + break; + case '~': + if (implicit && or) { + /* A | B & C == (A | B) & C */ + tmp = new_pattern (); + tmp->op = M_OR; + tmp->child = curlist; + curlist = tmp; + last = tmp; + or = 0; + } + + tmp = new_pattern (); + tmp->not = not; + tmp->alladdr = alladdr; + not = 0; + alladdr = 0; + + if (last) + last->next = tmp; + else + curlist = tmp; + last = tmp; + + ps.dptr++; /* move past the ~ */ + if ((entry = lookup_tag (*ps.dptr)) == NULL) { + snprintf (err->data, err->dsize, _("%c: invalid command"), *ps.dptr); + mutt_pattern_free (&curlist); + return NULL; + } + if (entry->class && (flags & entry->class) == 0) { + snprintf (err->data, err->dsize, _("%c: not supported in this mode"), + *ps.dptr); + mutt_pattern_free (&curlist); + return NULL; + } + tmp->op = entry->op; + + ps.dptr++; /* eat the operator and any optional whitespace */ + SKIPWS (ps.dptr); + + if (entry->eat_arg) { + if (!*ps.dptr) { + snprintf (err->data, err->dsize, _("missing parameter")); + mutt_pattern_free (&curlist); + return NULL; + } + if (entry->eat_arg (tmp, &ps, err) == -1) { + mutt_pattern_free (&curlist); + return NULL; + } + } + implicit = 1; + break; + case '(': + p = find_matching_paren (ps.dptr + 1); + if (*p != ')') { + snprintf (err->data, err->dsize, _("mismatched parenthesis: %s"), + ps.dptr); + mutt_pattern_free (&curlist); + return NULL; + } + /* compile the sub-expression */ + buf = str_substrdup (ps.dptr + 1, p); + if ((tmp = mutt_pattern_comp (buf, flags, err)) == NULL) { + mem_free (&buf); + mutt_pattern_free (&curlist); + return NULL; + } + mem_free (&buf); + if (last) + last->next = tmp; + else + curlist = tmp; + last = tmp; + tmp->not ^= not; + tmp->alladdr |= alladdr; + not = 0; + alladdr = 0; + ps.dptr = p + 1; /* restore location */ + break; + default: + snprintf (err->data, err->dsize, _("error in pattern at: %s"), ps.dptr); + mutt_pattern_free (&curlist); + return NULL; } } - if (!curlist) - { + if (!curlist) { strfcpy (err->data, _("empty pattern"), err->dsize); return NULL; } - if (curlist->next) - { + if (curlist->next) { tmp = new_pattern (); tmp->op = or ? M_OR : M_AND; tmp->child = curlist; @@ -863,7 +811,8 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err) } static int -perform_and (pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *hdr) +perform_and (pattern_t * pat, pattern_exec_flag flags, CONTEXT * ctx, + HEADER * hdr) { for (; pat; pat = pat->next) if (mutt_pattern_exec (pat, flags, ctx, hdr) <= 0) @@ -872,7 +821,8 @@ perform_and (pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *hdr) } static int -perform_or (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *hdr) +perform_or (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT * ctx, + HEADER * hdr) { for (; pat; pat = pat->next) if (mutt_pattern_exec (pat, flags, ctx, hdr) > 0) @@ -880,32 +830,29 @@ perform_or (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER return 0; } -static int match_adrlist (regex_t *rx, int match_personal, int alladdr, - int n, ...) +static int match_adrlist (regex_t * rx, int match_personal, int alladdr, + int n, ...) { va_list ap; ADDRESS *a; va_start (ap, n); - for ( ; n ; n --) - { - for (a = va_arg (ap, ADDRESS *) ; a ; a = a->next) - { - if (alladdr^ - ((a->mailbox && regexec (rx, a->mailbox, 0, NULL, 0) == 0) || - (match_personal && a->personal && - regexec (rx, a->personal, 0, NULL, 0) == 0))) - { - va_end (ap); - return (! alladdr); /* Found match, or non-match if alladdr */ + for (; n; n--) { + for (a = va_arg (ap, ADDRESS *); a; a = a->next) { + if (alladdr ^ + ((a->mailbox && regexec (rx, a->mailbox, 0, NULL, 0) == 0) || + (match_personal && a->personal && + regexec (rx, a->personal, 0, NULL, 0) == 0))) { + va_end (ap); + return (!alladdr); /* Found match, or non-match if alladdr */ } } } va_end (ap); - return alladdr; /* No matches, or all matches if alladdr */ + return alladdr; /* No matches, or all matches if alladdr */ } -static int match_reference (regex_t *rx, LIST *refs) +static int match_reference (regex_t * rx, LIST * refs) { for (; refs; refs = refs->next) if (regexec (rx, refs->data, 0, NULL, 0) == 0) @@ -913,159 +860,239 @@ static int match_reference (regex_t *rx, LIST *refs) return 0; } -int mutt_is_list_recipient (int alladdr, ADDRESS *a1, ADDRESS *a2) +int mutt_is_list_recipient (int alladdr, ADDRESS * a1, ADDRESS * a2) { - for (; a1 ; a1 = a1->next) + for (; a1; a1 = a1->next) if (alladdr ^ mutt_is_subscribed_list (a1)) - return (! alladdr); - for (; a2 ; a2 = a2->next) + return (!alladdr); + for (; a2; a2 = a2->next) if (alladdr ^ mutt_is_subscribed_list (a2)) - return (! alladdr); + return (!alladdr); return alladdr; } -int mutt_is_list_cc (int alladdr, ADDRESS *a1, ADDRESS *a2) +int mutt_is_list_cc (int alladdr, ADDRESS * a1, ADDRESS * a2) { - for (; a1 ; a1 = a1->next) + for (; a1; a1 = a1->next) if (alladdr ^ mutt_is_mail_list (a1)) - return (! alladdr); - for (; a2 ; a2 = a2->next) + return (!alladdr); + for (; a2; a2 = a2->next) if (alladdr ^ mutt_is_mail_list (a2)) - return (! alladdr); + return (!alladdr); return alladdr; } -static int match_user (int alladdr, ADDRESS *a1, ADDRESS *a2) +static int match_user (int alladdr, ADDRESS * a1, ADDRESS * a2) { - for (; a1 ; a1 = a1->next) + for (; a1; a1 = a1->next) if (alladdr ^ mutt_addr_is_user (a1)) - return (! alladdr); - for (; a2 ; a2 = a2->next) + return (!alladdr); + for (; a2; a2 = a2->next) if (alladdr ^ mutt_addr_is_user (a2)) - return (! alladdr); + return (!alladdr); return alladdr; } +/* test if name is considered a real name, i.e. consists of at least 2 + * space-separated words of which none may end in a dot + */ +static int valid_realname (const char *name) +{ + const char *p = name; + int ret = 0; + + while (*p) { + if (isspace (*p)) + ret++; + else if (*p == '.') + /* skip abbr. parts of names (e.g. 'J. User') */ + ret--; + p++; + } + return (ret >= 1); +} + /* flags M_MATCH_FULL_ADDRESS match both personal and machine address */ int -mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h) +mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, + CONTEXT * ctx, HEADER * h) { char buf[STRING]; - switch (pat->op) - { - case M_AND: - return (pat->not ^ (perform_and (pat->child, flags, ctx, h) > 0)); - case M_OR: - return (pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0)); - case M_ALL: - return (!pat->not); - case M_EXPIRED: - return (pat->not ^ h->expired); - case M_SUPERSEDED: - return (pat->not ^ h->superseded); - case M_FLAG: - return (pat->not ^ h->flagged); - case M_TAG: - return (pat->not ^ h->tagged); - case M_NEW: - return (pat->not ? h->old || h->read : !(h->old || h->read)); - case M_UNREAD: - return (pat->not ? h->read : !h->read); - case M_REPLIED: - return (pat->not ^ h->replied); - case M_OLD: - return (pat->not ? (!h->old || h->read) : (h->old && !h->read)); - case M_READ: - return (pat->not ^ h->read); - case M_DELETED: - return (pat->not ^ h->deleted); - case M_MESSAGE: - return (pat->not ^ (h->msgno >= pat->min - 1 && (pat->max == M_MAXRANGE || - h->msgno <= pat->max - 1))); - case M_DATE: - return (pat->not ^ (h->date_sent >= pat->min && h->date_sent <= pat->max)); - case M_DATE_RECEIVED: - return (pat->not ^ (h->received >= pat->min && h->received <= pat->max)); - case M_BODY: - case M_HEADER: - case M_WHOLE_MSG: - return (pat->not ^ msg_search (ctx, pat->rx, buf, sizeof (buf), pat->op, h->msgno)); - case M_SENDER: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 1, h->env->sender)); - case M_FROM: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 1, h->env->from)); - case M_TO: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 1, h->env->to)); - case M_CC: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 1, h->env->cc)); - case M_SUBJECT: - return (pat->not ^ (h->env->subject && regexec (pat->rx, h->env->subject, 0, NULL, 0) == 0)); - case M_ID: - return (pat->not ^ (h->env->message_id && regexec (pat->rx, h->env->message_id, 0, NULL, 0) == 0)); - case M_SCORE: - return (pat->not ^ (h->score >= pat->min && (pat->max == M_MAXRANGE || - h->score <= pat->max))); - case M_SIZE: - return (pat->not ^ (h->content->length >= pat->min && (pat->max == M_MAXRANGE || h->content->length <= pat->max))); - case M_REFERENCE: - return (pat->not ^ match_reference (pat->rx, h->env->references)); - case M_ADDRESS: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 4, h->env->from, - h->env->sender, h->env->to, h->env->cc)); - case M_RECIPIENT: - return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, - pat->alladdr, 2, h->env->to, h->env->cc)); - case M_LIST: - return (pat->not ^ mutt_is_list_recipient (pat->alladdr, h->env->to, h->env->cc)); - case M_PERSONAL_RECIP: - return (pat->not ^ match_user (pat->alladdr, h->env->to, h->env->cc)); - case M_PERSONAL_FROM: - return (pat->not ^ match_user (pat->alladdr, h->env->from, NULL)); - case M_COLLAPSED: - return (pat->not ^ (h->collapsed && h->num_hidden > 1)); - case M_CRYPT_SIGN: - if (!WithCrypto) - break; - return (pat->not ^ ((h->security & SIGN) ? 1 : 0)); - case M_CRYPT_VERIFIED: - if (!WithCrypto) - break; - return (pat->not ^ ((h->security & GOODSIGN) ? 1 : 0)); - case M_CRYPT_ENCRYPT: - if (!WithCrypto) - break; - return (pat->not ^ ((h->security & ENCRYPT) ? 1 : 0)); - case M_PGP_KEY: - if (!(WithCrypto & APPLICATION_PGP)) - break; - return (pat->not ^ ((h->security & APPLICATION_PGP) && (h->security & PGPKEY))); - case M_XLABEL: - return (pat->not ^ (h->env->x_label && regexec (pat->rx, h->env->x_label, 0, NULL, 0) == 0)); - case M_DUPLICATED: - return (pat->not ^ (h->thread && h->thread->duplicate_thread)); + switch (pat->op) { + case M_AND: + return (pat->not ^ (perform_and (pat->child, flags, ctx, h) > 0)); + case M_OR: + return (pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0)); + case M_ALL: + return (!pat->not); + case M_EXPIRED: + return (pat->not ^ h->expired); + case M_SUPERSEDED: + return (pat->not ^ h->superseded); + case M_FLAG: + return (pat->not ^ h->flagged); + case M_TAG: + return (pat->not ^ h->tagged); + case M_NEW: + return (pat->not ? h->old || h->read : !(h->old || h->read)); + case M_UNREAD: + return (pat->not ? h->read : !h->read); + case M_REPLIED: + return (pat->not ^ h->replied); + case M_OLD: + return (pat->not ? (!h->old || h->read) : (h->old && !h->read)); + case M_READ: + return (pat->not ^ h->read); + case M_DELETED: + return (pat->not ^ h->deleted); + case M_MESSAGE: + return (pat->not ^ (h->msgno >= pat->min - 1 && (pat->max == M_MAXRANGE || + h->msgno <= + pat->max - 1))); + case M_DATE: + return (pat-> + not ^ (h->date_sent >= pat->min && h->date_sent <= pat->max)); + case M_DATE_RECEIVED: + return (pat->not ^ (h->received >= pat->min && h->received <= pat->max)); + case M_BODY: + case M_HEADER: + case M_WHOLE_MSG: + return (pat-> + not ^ msg_search (ctx, pat->rx, buf, sizeof (buf), pat->op, + h->msgno)); + case M_SENDER: + return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 1, h->env->sender)); + case M_FROM: + return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 1, h->env->from)); + case M_TO: + return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 1, h->env->to)); + case M_CC: + return (pat->not ^ match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 1, h->env->cc)); + case M_SUBJECT: + return (pat-> + not ^ (h->env && h->env->subject + && regexec (pat->rx, h->env->subject, 0, NULL, 0) == 0)); + case M_ID: + return (pat-> + not ^ (h->env && h->env->message_id + && regexec (pat->rx, h->env->message_id, 0, NULL, + 0) == 0)); + case M_SCORE: + return (pat->not ^ (h->score >= pat->min && (pat->max == M_MAXRANGE || + h->score <= pat->max))); + case M_SIZE: + return (pat-> + not ^ (h->content->length >= pat->min + && (pat->max == M_MAXRANGE + || h->content->length <= pat->max))); + case M_REFERENCE: + return (pat->not ^ match_reference (pat->rx, h->env->references)); + case M_ADDRESS: + return (pat-> + not ^ (h->env + && match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 4, h->env->from, + h->env->sender, h->env->to, + h->env->cc))); + case M_RECIPIENT: + return (pat-> + not ^ (h->env + && match_adrlist (pat->rx, flags & M_MATCH_FULL_ADDRESS, + pat->alladdr, 2, h->env->to, + h->env->cc))); + case M_LIST: + return (pat-> + not ^ (h->env + && mutt_is_list_cc (pat->alladdr, h->env->to, + h->env->cc))); + case M_SUBSCRIBED_LIST: + return (pat-> + not ^ (h->env + && mutt_is_list_recipient (pat->alladdr, h->env->to, + h->env->cc))); + case M_PERSONAL_RECIP: + return (pat-> + not ^ (h->env + && match_user (pat->alladdr, h->env->to, h->env->cc))); + case M_PERSONAL_FROM: + return (pat-> + not ^ (h->env && match_user (pat->alladdr, h->env->from, NULL))); + case M_COLLAPSED: + return (pat->not ^ (h->collapsed && h->num_hidden > 1)); + case M_CRYPT_SIGN: + if (!WithCrypto) + break; + return (pat->not ^ ((h->security & SIGN) ? 1 : 0)); + case M_CRYPT_VERIFIED: + if (!WithCrypto) + break; + return (pat->not ^ ((h->security & GOODSIGN) ? 1 : 0)); + case M_CRYPT_ENCRYPT: + if (!WithCrypto) + break; + return (pat->not ^ ((h->security & ENCRYPT) ? 1 : 0)); + case M_PGP_KEY: + if (!(WithCrypto & APPLICATION_PGP)) + break; + return (pat->not ^ ((h->security & APPLICATION_PGP) + && (h->security & PGPKEY))); + case M_XLABEL: + return (pat-> + not ^ (h->env->x_label + && regexec (pat->rx, h->env->x_label, 0, NULL, 0) == 0)); + case M_HORMEL: + return (pat-> + not ^ (h->env->spam && h->env->spam->data + && regexec (pat->rx, h->env->spam->data, 0, NULL, + 0) == 0)); + case M_DUPLICATED: + return (pat->not ^ (h->thread && h->thread->duplicate_thread)); + case M_UNREFERENCED: + return (pat->not ^ (h->thread && !h->thread->child)); + case M_MULTIPART: + return (pat->not ^ (h->content && h->content->type == TYPEMULTIPART)); + case M_REALNAME: + /* realname filter: + * we have a match if + * - From: matches $alternates + * - or we have an alias for current address + * - or From: contains valid email address _and_ name has >= 2 fields + */ + return (pat-> + not ^ (h->env && h->env->from && (mutt_addr_is_user (h->env->from) + || + (alias_reverse_lookup + (h->env->from) != NULL) + || (h->env->from->personal + && valid_realname (h->env-> + from-> + personal) + && h->env->from->mailbox) + ))); #ifdef USE_NNTP - case M_NEWSGROUPS: - return (pat->not ^ (h->env->newsgroups && regexec (pat->rx, h->env->newsgroups, 0, NULL, 0) == 0)); + case M_NEWSGROUPS: + return (pat-> + not ^ (h->env->newsgroups + && regexec (pat->rx, h->env->newsgroups, 0, NULL, + 0) == 0)); #endif } mutt_error (_("error: unknown op %d (report this error)."), pat->op); return (-1); } -static void quote_simple(char *tmp, size_t len, const char *p) +static void quote_simple (char *tmp, size_t len, const char *p) { int i = 0; - + tmp[i++] = '"'; - while (*p && i < len - 3) - { + while (*p && i < len - 3) { if (*p == '\\' || *p == '"') tmp[i++] = '\\'; tmp[i++] = *p++; @@ -1073,7 +1100,7 @@ static void quote_simple(char *tmp, size_t len, const char *p) tmp[i++] = '"'; tmp[i] = 0; } - + /* convert a simple search into a real request */ void mutt_check_simple (char *s, size_t len, const char *simple) { @@ -1082,12 +1109,10 @@ void mutt_check_simple (char *s, size_t len, const char *simple) /* XXX - is ascii_strcasecmp() right here, or should we use locale's * equivalences? */ - - if (!strchr (s, '~')) /* yup, so spoof a real request */ - { + + if (!strchr (s, '~')) { /* yup, so spoof a real request */ /* convert old tokens into the new format */ - if (ascii_strcasecmp ("all", s) == 0 || - !mutt_strcmp ("^", s) || !mutt_strcmp (".", s)) /* ~A is more efficient */ + if (ascii_strcasecmp ("all", s) == 0 || !str_cmp ("^", s) || !str_cmp (".", s)) /* ~A is more efficient */ strfcpy (s, "~A", len); else if (ascii_strcasecmp ("del", s) == 0) strfcpy (s, "~D", len); @@ -1105,9 +1130,8 @@ void mutt_check_simple (char *s, size_t len, const char *simple) strfcpy (s, "~T", len); else if (ascii_strcasecmp ("unread", s) == 0) strfcpy (s, "~U", len); - else - { - quote_simple (tmp, sizeof(tmp), s); + else { + quote_simple (tmp, sizeof (tmp), s); mutt_expand_fmt (s, len, simple, tmp); } } @@ -1122,19 +1146,24 @@ int mutt_pattern_func (int op, char *prompt) strfcpy (buf, NONULL (Context->pattern), sizeof (buf)); if (prompt || op != M_LIMIT) - if (mutt_get_field (prompt, buf, sizeof (buf), M_PATTERN | M_CLEAR) != 0 || !buf[0]) - return (-1); + if (mutt_get_field (prompt, buf, sizeof (buf), M_PATTERN | M_CLEAR) != 0) + return (-1); + if (!buf[0]) { + if (op == M_LIMIT) + strncpy (buf, "~A", sizeof (buf)); + else + return (-1); + } mutt_message _("Compiling search pattern..."); - - simple = safe_strdup (buf); + + simple = str_dup (buf); mutt_check_simple (buf, sizeof (buf), NONULL (SimpleSearch)); err.data = error; err.dsize = sizeof (error); - if ((pat = mutt_pattern_comp (buf, M_FULL_MSG, &err)) == NULL) - { - FREE (&simple); + if ((pat = mutt_pattern_comp (buf, M_FULL_MSG, &err)) == NULL) { + mem_free (&simple); mutt_error ("%s", err.data); return (-1); } @@ -1143,51 +1172,47 @@ int mutt_pattern_func (int op, char *prompt) #define THIS_BODY Context->hdrs[i]->content - if (op == M_LIMIT) - { - Context->vcount = 0; - Context->vsize = 0; + if (op == M_LIMIT) { + Context->vcount = 0; + Context->vsize = 0; Context->collapsed = 0; - for (i = 0; i < Context->msgcount; i++) - { + for (i = 0; i < Context->msgcount; i++) { /* new limit pattern implicitly uncollapses all threads */ Context->hdrs[i]->virtual = -1; Context->hdrs[i]->limited = 0; Context->hdrs[i]->collapsed = 0; Context->hdrs[i]->num_hidden = 0; - if (mutt_pattern_exec (pat, M_MATCH_FULL_ADDRESS, Context, Context->hdrs[i])) - { - Context->hdrs[i]->virtual = Context->vcount; - Context->hdrs[i]->limited = 1; - Context->v2r[Context->vcount] = i; - Context->vcount++; - Context->vsize+=THIS_BODY->length + THIS_BODY->offset - - THIS_BODY->hdr_offset; + if (mutt_pattern_exec + (pat, M_MATCH_FULL_ADDRESS, Context, Context->hdrs[i])) { + Context->hdrs[i]->virtual = Context->vcount; + Context->hdrs[i]->limited = 1; + Context->v2r[Context->vcount] = i; + Context->vcount++; + Context->vsize += THIS_BODY->length + THIS_BODY->offset - + THIS_BODY->hdr_offset; } } } - else - { - for (i = 0; i < Context->vcount; i++) - { - if (mutt_pattern_exec (pat, M_MATCH_FULL_ADDRESS, Context, Context->hdrs[Context->v2r[i]])) - { - switch (op) - { - case M_UNDELETE: - mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_PURGED, - 0); - case M_DELETE: - mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_DELETE, - (op == M_DELETE)); - break; - case M_TAG: - case M_UNTAG: - mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_TAG, - (op == M_TAG)); - break; - } + else { + for (i = 0; i < Context->vcount; i++) { + if (mutt_pattern_exec + (pat, M_MATCH_FULL_ADDRESS, Context, + Context->hdrs[Context->v2r[i]])) { + switch (op) { + case M_UNDELETE: + mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_PURGED, + 0); + case M_DELETE: + mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_DELETE, + (op == M_DELETE)); + break; + case M_TAG: + case M_UNTAG: + mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_TAG, + (op == M_TAG)); + break; + } } } } @@ -1196,32 +1221,23 @@ int mutt_pattern_func (int op, char *prompt) mutt_clear_error (); - if (op == M_LIMIT) - { - FREE (&Context->pattern); - if (Context->limit_pattern) + if (op == M_LIMIT) { + /* drop previous limit pattern */ + mem_free (&Context->pattern); + if (Context->limit_pattern) mutt_pattern_free (&Context->limit_pattern); - if (!Context->vcount) - { + if (Context->msgcount && !Context->vcount) { mutt_error _("No messages matched criteria."); -#if 0 - Context->vcount = Context->msgcount; - /* restore full display */ - for (i = 0; i < Context->msgcount; i++) - { - Context->hdrs[i]->virtual = i; - Context->v2r[i] = i; - } -#endif } - else if (mutt_strncmp (buf, "~A", 2) != 0) - { + + /* record new limit pattern, unless match all */ + if (str_ncmp (buf, "~A", 2) != 0) { Context->pattern = simple; - simple = NULL; /* don't clobber it */ + simple = NULL; /* don't clobber it */ Context->limit_pattern = mutt_pattern_comp (buf, M_FULL_MSG, &err); } } - FREE (&simple); + mem_free (&simple); mutt_pattern_free (&pat); return 0; } @@ -1235,13 +1251,12 @@ int mutt_search_command (int cur, int op) BUFFER err; int incr; HEADER *h; - - if (op != OP_SEARCH_NEXT && op != OP_SEARCH_OPPOSITE) - { + + if (op != OP_SEARCH_NEXT && op != OP_SEARCH_OPPOSITE) { strfcpy (buf, LastSearch, sizeof (buf)); if (mutt_get_field ((op == OP_SEARCH) ? _("Search for: ") : - _("Reverse search for: "), buf, sizeof (buf), - M_CLEAR | M_PATTERN) != 0 || !buf[0]) + _("Reverse search for: "), buf, sizeof (buf), + M_CLEAR | M_PATTERN) != 0 || !buf[0]) return (-1); if (op == OP_SEARCH) @@ -1254,30 +1269,29 @@ int mutt_search_command (int cur, int op) strfcpy (temp, buf, sizeof (temp)); mutt_check_simple (temp, sizeof (temp), NONULL (SimpleSearch)); - if (!SearchPattern || mutt_strcmp (temp, LastSearchExpn)) - { + if (!SearchPattern || str_cmp (temp, LastSearchExpn)) { set_option (OPTSEARCHINVALID); strfcpy (LastSearch, buf, sizeof (LastSearch)); mutt_message _("Compiling search pattern..."); + mutt_pattern_free (&SearchPattern); err.data = error; err.dsize = sizeof (error); - if ((SearchPattern = mutt_pattern_comp (temp, M_FULL_MSG, &err)) == NULL) - { - mutt_error ("%s", error); - return (-1); + if ((SearchPattern = + mutt_pattern_comp (temp, M_FULL_MSG, &err)) == NULL) { + mutt_error ("%s", error); + return (-1); } mutt_clear_error (); } } - else if (!SearchPattern) - { + else if (!SearchPattern) { mutt_error _("No search pattern."); + return (-1); } - if (option (OPTSEARCHINVALID)) - { + if (option (OPTSEARCHINVALID)) { for (i = 0; i < Context->msgcount; i++) Context->hdrs[i]->searched = 0; unset_option (OPTSEARCHINVALID); @@ -1287,49 +1301,48 @@ int mutt_search_command (int cur, int op) if (op == OP_SEARCH_OPPOSITE) incr = -incr; - for (i = cur + incr, j = 0 ; j != Context->vcount; j++) - { - if (i > Context->vcount - 1) - { + for (i = cur + incr, j = 0; j != Context->vcount; j++) { + if (i > Context->vcount - 1) { i = 0; if (option (OPTWRAPSEARCH)) - mutt_message _("Search wrapped to top."); - else - { + mutt_message (_("Search wrapped to top.")); + + else { mutt_message _("Search hit bottom without finding match"); - return (-1); + + return (-1); } } - else if (i < 0) - { + else if (i < 0) { i = Context->vcount - 1; if (option (OPTWRAPSEARCH)) - mutt_message _("Search wrapped to bottom."); - else - { + mutt_message (_("Search wrapped to bottom.")); + + else { mutt_message _("Search hit top without finding match"); - return (-1); + + return (-1); } } h = Context->hdrs[Context->v2r[i]]; - if (h->searched) - { + if (h->searched) { /* if we've already evaulated this message, use the cached value */ if (h->matched) - return i; + return i; } - else - { + else { /* remember that we've already searched this message */ h->searched = 1; - if ((h->matched = (mutt_pattern_exec (SearchPattern, M_MATCH_FULL_ADDRESS, Context, h) > 0))) - return i; + if ((h->matched = + (mutt_pattern_exec + (SearchPattern, M_MATCH_FULL_ADDRESS, Context, h) > 0))) + return i; } - if (SigInt) - { + if (SigInt) { mutt_error _("Search interrupted."); + SigInt = 0; return (-1); } @@ -1338,5 +1351,6 @@ int mutt_search_command (int cur, int op) } mutt_error _("Not found."); + return (-1); }