#include <lib-lib/lib-lib.h>
#include <lib-mime/mime.h>
-#include <lib-ui/enter.h>
-#include <lib-ui/curses.h>
+#include <lib-ui/lib-ui.h>
#include <lib-mx/mx.h>
+#include <imap/imap.h>
-#include "mutt.h"
+#include "pattern.h"
#include "alias.h"
+#include "crypt.h"
#include "handler.h"
#include "keymap.h"
#include "copy.h"
-#include <imap/imap.h>
-
-#include <lib-crypt/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 patmatch (const pattern_t* pat, const char* buf);
-struct pattern_flags {
+static 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[] = {
+} const Flags[] = {
{'A', M_ALL, 0, NULL},
{'b', M_BODY, M_FULL_MSG, eat_regexp},
{'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp},
{'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},
-#endif
{'x', M_REFERENCE, 0, eat_regexp},
{'X', M_MIMEATTACH, 0, eat_range},
{'y', M_XLABEL, 0, eat_regexp},
#define M_PDR_ERROR 0x0100
#define M_PDR_ERRORDONE (M_PDR_ERROR | M_PDR_DONE)
+void pattern_wipe(pattern_t *pat)
+{
+ if (pat->rx) {
+ regfree (pat->rx);
+ p_delete(&pat->rx);
+ }
+ p_delete(&pat->str);
+ pattern_list_wipe(&pat->child);
+}
+
/* if no uppercase letters are given, do a case-insensitive search */
int mutt_which_case (const char *s)
{
p_clear(&s, 1);
s.fpin = msg->fp;
s.flags = M_CHARCONV;
- s.fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
+ s.fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(mod_core.tmpdir), NULL);
if (!s.fpout) {
mutt_error(_("Could not create temporary file"));
- return (0);
+ return 0;
}
if (pat->op != M_BODY)
if (pat->op != M_HEADER) {
mutt_parse_mime_message (ctx, h);
-
- if ((h->security & ENCRYPT) && !crypt_valid_passphrase (h->security))
- {
- mx_close_message (&msg);
- if (fp) {
- m_fclose(&fp);
- unlink (tempfile);
- }
- return (0);
- }
-
fseeko (msg->fp, h->offset, 0);
mutt_body_handler (h->content, &s);
}
if (mutt_extract_token (&buf, s, M_TOKEN_PATTERN | M_TOKEN_COMMENT) != 0 ||
!buf.data) {
snprintf (err->data, err->dsize, _("Error in expression: %s"), s->dptr);
- return (-1);
+ return -1;
}
if (!*buf.data) {
snprintf (err->data, err->dsize, _("Empty expression"));
- return (-1);
+ return -1;
}
if (pat->stringmatch) {
regerror (r, pat->rx, err->data, err->dsize);
regfree (pat->rx);
p_delete(&pat->rx);
- return (-1);
+ return -1;
}
}
return 0;
default:
return s;
}
- mutt_normalize_time (tm);
- return (ps + 1);
+ mktime(tm);
+ return ps + 1;
}
static void adjust_date_range (struct tm *min, struct tm *max)
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);
+ return (flag & M_PDR_ERROR) ? NULL : pc;
}
static int eat_date (pattern_t * pat, BUFFER * s, BUFFER * err)
if (mutt_extract_token (&buffer, s, M_TOKEN_COMMENT | M_TOKEN_PATTERN) != 0
|| !buffer.data) {
m_strcpy(err->data, err->dsize, _("error in expression"));
- return (-1);
+ return -1;
}
p_clear(&min, 1);
/* mininum date specified */
if ((pc = getDate (pc, &min, err)) == NULL) {
p_delete(&buffer.data);
- return (-1);
+ return -1;
}
haveMin = TRUE;
pc = vskipspaces(pc);
if (!parse_date_range (pc, &min, &max, haveMin, &baseMin, err)) { /* bail out on any parsing error */
p_delete(&buffer.data);
- return (-1);
+ return -1;
}
}
}
/* Since we allow two dates to be specified we'll have to adjust that. */
adjust_date_range (&min, &max);
- pat->min = mutt_mktime (&min, 1);
- pat->max = mutt_mktime (&max, 1);
+ pat->min = mktime(&min);
+ pat->max = mktime(&max);
p_delete(&buffer.data);
return 0;
}
-static struct pattern_flags *lookup_tag (char tag)
+static const struct pattern_flags *lookup_tag (char tag)
{
int i;
for (i = 0; Flags[i].tag; i++)
if (Flags[i].tag == tag)
- return (&Flags[i]);
+ return &Flags[i];
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++) {
- if (*s == '(')
- level++;
- else if (*s == ')') {
- level--;
- if (!level)
- break;
- }
- }
- return s;
-}
-
-void mutt_pattern_free (pattern_t ** pat)
-{
- pattern_t *tmp;
-
- while (*pat) {
- tmp = *pat;
- *pat = (*pat)->next;
+ int level = 1;
- if (tmp->rx) {
- regfree (tmp->rx);
- p_delete(&tmp->rx);
+ for (; *s; s++) {
+ level += (*s == '(') - (*s == ')');
+ if (!level)
+ break;
}
- p_delete(&tmp->str);
- if (tmp->child)
- mutt_pattern_free (&tmp->child);
- p_delete(&tmp);
- }
+ return s;
}
-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;
int alladdr = 0;
int or = 0;
int implicit = 1; /* used to detect logical AND operator */
- struct pattern_flags *entry;
+ const struct pattern_flags *entry;
char *p;
char *buf;
BUFFER ps;
p_clear(&ps, 1);
- ps.dptr = s;
+ ps.dptr = s;
ps.dsize = m_strlen(s);
while (*ps.dptr) {
}
if (curlist->next) {
/* A & B | C == (A & B) | C */
- tmp = new_pattern ();
+ tmp = pattern_new();
tmp->op = M_AND;
tmp->child = curlist;
case '~':
if (implicit && or) {
/* A | B & C == (A | B) & C */
- tmp = new_pattern ();
+ tmp = pattern_new();
tmp->op = M_OR;
tmp->child = curlist;
curlist = tmp;
or = 0;
}
- tmp = new_pattern ();
+ tmp = pattern_new();
tmp->not = not;
tmp->alladdr = alladdr;
tmp->stringmatch = (*ps.dptr == '=') ? 1 : 0;
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);
+ pattern_list_wipe(&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);
+ pattern_list_wipe(&curlist);
return NULL;
}
tmp->op = entry->op;
if (entry->eat_arg) {
if (!*ps.dptr) {
snprintf (err->data, err->dsize, _("missing parameter"));
- mutt_pattern_free (&curlist);
+ pattern_list_wipe(&curlist);
return NULL;
}
if (entry->eat_arg (tmp, &ps, err) == -1) {
- mutt_pattern_free (&curlist);
+ pattern_list_wipe(&curlist);
return NULL;
}
}
if (*p != ')') {
snprintf (err->data, err->dsize, _("mismatched parenthesis: %s"),
ps.dptr);
- mutt_pattern_free (&curlist);
+ pattern_list_wipe(&curlist);
return NULL;
}
/* compile the sub-expression */
buf = p_dupstr(ps.dptr + 1, p - ps.dptr - 1);
if ((tmp = mutt_pattern_comp (buf, flags, err)) == NULL) {
p_delete(&buf);
- mutt_pattern_free (&curlist);
+ pattern_list_wipe(&curlist);
return NULL;
}
p_delete(&buf);
break;
default:
snprintf (err->data, err->dsize, _("error in pattern at: %s"), ps.dptr);
- mutt_pattern_free (&curlist);
+ pattern_list_wipe(&curlist);
return NULL;
}
}
return NULL;
}
if (curlist->next) {
- tmp = new_pattern ();
+ tmp = pattern_new();
tmp->op = or ? M_OR : M_AND;
tmp->child = curlist;
curlist = tmp;
}
- return (curlist);
+ return curlist;
}
static int
(match_personal && a->personal &&
patmatch (pat, a->personal) == 0))) {
va_end (ap);
- return (!pat->alladdr); /* Found match, or non-match if alladdr */
+ return !pat->alladdr; /* Found match, or non-match if alladdr */
}
}
}
{
for (; a1; a1 = a1->next)
if (alladdr ^ mutt_is_subscribed_list (a1))
- return (!alladdr);
+ return !alladdr;
for (; a2; a2 = a2->next)
if (alladdr ^ mutt_is_subscribed_list (a2))
- return (!alladdr);
+ return !alladdr;
return alladdr;
}
{
for (; a1; a1 = a1->next)
if (alladdr ^ mutt_is_mail_list (a1))
- return (!alladdr);
+ return !alladdr;
for (; a2; a2 = a2->next)
if (alladdr ^ mutt_is_mail_list (a2))
- return (!alladdr);
+ return !alladdr;
return alladdr;
}
{
for (; a1; a1 = a1->next)
if (alladdr ^ mutt_addr_is_user (a1))
- return (!alladdr);
+ return !alladdr;
for (; a2; a2 = a2->next)
if (alladdr ^ mutt_addr_is_user (a2))
- return (!alladdr);
+ return !alladdr;
return alladdr;
}
ret--;
p++;
}
- return (ret >= 1);
+ return ret >= 1;
}
/* flags
{
switch (pat->op) {
case M_AND:
- return (pat->not ^ (perform_and (pat->child, flags, ctx, h) > 0));
+ 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));
+ return pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0);
case M_ALL:
- return (!pat->not);
+ return !pat->not;
case M_EXPIRED:
- return (pat->not ^ h->expired);
+ return pat->not ^ h->expired;
case M_SUPERSEDED:
- return (pat->not ^ h->superseded);
+ return pat->not ^ h->superseded;
case M_FLAG:
- return (pat->not ^ h->flagged);
+ return pat->not ^ h->flagged;
case M_TAG:
- return (pat->not ^ h->tagged);
+ return pat->not ^ h->tagged;
case M_NEW:
- return (pat->not ? h->old || h->read : !(h->old || h->read));
+ return pat->not ? h->old || h->read : !(h->old || h->read);
case M_UNREAD:
- return (pat->not ? h->read : !h->read);
+ return pat->not ? h->read : !h->read;
case M_REPLIED:
- return (pat->not ^ h->replied);
+ return pat->not ^ h->replied;
case M_OLD:
- return (pat->not ? (!h->old || h->read) : (h->old && !h->read));
+ return pat->not ? (!h->old || h->read) : (h->old && !h->read);
case M_READ:
- return (pat->not ^ h->read);
+ return pat->not ^ h->read;
case M_DELETED:
- return (pat->not ^ h->deleted);
+ return pat->not ^ h->deleted;
case M_MESSAGE:
return (pat->not ^ (h->msgno >= pat->min - 1 && (pat->max == M_MAXRANGE ||
h->msgno <=
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));
+ return pat->not ^ (h->received >= pat->min && h->received <= pat->max);
case M_BODY:
case M_HEADER:
case M_WHOLE_MSG:
/* IMAP search sets h->matched at search compile time */
if (ctx->magic == M_IMAP && pat->stringmatch)
- return (h->matched);
- return (pat->not ^ msg_search (ctx, pat, h->msgno));
+ return h->matched;
+ return pat->not ^ msg_search (ctx, pat, h->msgno);
case M_SENDER:
return (pat->not ^ match_adrlist (pat, flags & M_MATCH_FULL_ADDRESS,
pat->alladdr, 1, h->env->sender));
&& (pat->max == M_MAXRANGE
|| h->content->length <= pat->max)));
case M_REFERENCE:
- return (pat->not ^ match_reference (pat, h->env->references));
+ return pat->not ^ match_reference (pat, h->env->references);
case M_ADDRESS:
return (pat->
not ^ (h->env
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));
+ return pat->not ^ (h->collapsed && h->num_hidden > 1);
case M_CRYPT_SIGN:
- return (pat->not ^ ((h->security & SIGN) ? 1 : 0));
+ return pat->not ^ ((h->security & SIGN) ? 1 : 0);
case M_CRYPT_VERIFIED:
- return (pat->not ^ ((h->security & GOODSIGN) ? 1 : 0));
+ return pat->not ^ ((h->security & GOODSIGN) ? 1 : 0);
case M_CRYPT_ENCRYPT:
- return (pat->not ^ ((h->security & ENCRYPT) ? 1 : 0));
+ return pat->not ^ ((h->security & ENCRYPT) ? 1 : 0);
case M_PGP_KEY:
return (pat->not ^ ((h->security & APPLICATION_PGP)
&& (h->security & PGPKEY)));
not ^ (h->env->spam && h->env->spam->data
&& patmatch (pat, h->env->spam->data) == 0));
case M_DUPLICATED:
- return (pat->not ^ (h->thread && h->thread->duplicate_thread));
+ return pat->not ^ (h->thread && h->thread->duplicate_thread);
case M_MIMEATTACH:
{
}
case M_UNREFERENCED:
- return (pat->not ^ (h->thread && !h->thread->child));
+ return pat->not ^ (h->thread && !h->thread->child);
case M_MULTIPART:
- return (pat->not ^ (h->content && h->content->type == TYPEMULTIPART));
+ return pat->not ^ (h->content && h->content->type == TYPEMULTIPART);
case M_REALNAME:
/* realname filter:
* we have a match if
&& valid_realname(h->env-> from->personal)
&& h->env->from->mailbox)
)) ^ pat->not;
-#ifdef USE_NNTP
- case M_NEWSGROUPS:
- return (pat->
- not ^ (h->env->newsgroups
- && patmatch (pat, h->env->newsgroups) == 0));
-#endif
}
mutt_error (_("error: unknown op %d (report this error)."), pat->op);
- return (-1);
+ return -1;
}
static void quote_simple (char *tmp, ssize_t len, const char *p)
}
}
-int mutt_pattern_func (int op, char *prompt)
+int mutt_pattern_func (int op, const char *prompt)
{
pattern_t *pat;
char buf[LONG_STRING] = "", *simple, error[STRING];
m_strcpy(buf, sizeof(buf), NONULL(Context->pattern));
if (prompt || op != M_LIMIT)
if (mutt_get_field (prompt, buf, sizeof (buf), M_PATTERN | M_CLEAR) != 0 || !buf[0])
- return (-1);
+ return -1;
mutt_message _("Compiling search pattern...");
if ((pat = mutt_pattern_comp (buf, M_FULL_MSG, &err)) == NULL) {
p_delete(&simple);
mutt_error ("%s", err.data);
- return (-1);
+ return -1;
}
if (Context->magic == M_IMAP && imap_search (Context, pat) < 0)
/* drop previous limit pattern */
p_delete(&Context->pattern);
if (Context->limit_pattern)
- mutt_pattern_free (&Context->limit_pattern);
+ pattern_list_wipe(&Context->limit_pattern);
if (Context->msgcount && !Context->vcount) {
mutt_error _("No messages matched criteria.");
}
}
}
p_delete(&simple);
- mutt_pattern_free (&pat);
+ pattern_list_wipe(&pat);
return 0;
}
if (mutt_get_field ((op == OP_SEARCH) ? _("Search for: ") :
_("Reverse search for: "), buf, sizeof (buf),
M_CLEAR | M_PATTERN) != 0 || !buf[0])
- return (-1);
+ return -1;
if (op == OP_SEARCH)
unset_option (OPTSEARCHREVERSE);
m_strcpy(LastSearch, sizeof(LastSearch), buf);
mutt_message _("Compiling search pattern...");
- mutt_pattern_free (&SearchPattern);
+ pattern_list_wipe(&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);
+ return -1;
}
mutt_clear_error ();
}
else if (!SearchPattern) {
mutt_error _("No search pattern.");
- return (-1);
+ return -1;
}
if (option (OPTSEARCHINVALID)) {
else {
mutt_message _("Search hit bottom without finding match");
- return (-1);
+ return -1;
}
}
else if (i < 0) {
else {
mutt_message _("Search hit top without finding match");
- return (-1);
+ return -1;
}
}
mutt_error _("Search interrupted.");
SigInt = 0;
- return (-1);
+ return -1;
}
i += incr;
mutt_error _("Not found.");
- return (-1);
+ return -1;
}