if (s->flags & M_CHARCONV) {
const char *charset = parameter_getval(b->parameter, "charset");
- if (!option (OPTSTRICTMIME) && !charset)
+ if (!charset)
charset = charset_getfirst(AssumedCharset);
if (charset && Charset)
cd = mutt_iconv_open (Charset, charset, M_ICONV_HOOK_FROM);
- }
- else {
+ } else {
if (b->file_charset)
cd = mutt_iconv_open (Charset, b->file_charset, M_ICONV_HOOK_FROM);
}
#include <lib-crypt/crypt.h>
#include "alias.h"
+#include "pattern.h"
#define ERROR_STOP 0
if (h->rx.rx) {
regfree (h->rx.rx);
}
- mutt_pattern_free (&h->pattern);
+ pattern_list_wipe(&h->pattern);
p_delete(&h);
}
#include "mutt.h"
#include "globals.h"
+#include "pattern.h"
#include "sort.h"
#include "browser.h"
#include "message.h"
** DOING!\fP
*/
#ifdef USE_HCACHE
-
{"header_cache", DT_PATH, R_NONE, UL &HeaderCache, "" },
/*
** .pp
** menu, attachments which cannot be decoded in a reasonable manner will
** be attached to the newly composed message if this option is set.
*/
-
#ifdef USE_NNTP
{"nntp_mime_subject", DT_BOOL, R_NONE, OPTMIMESUBJECT, "yes" },
/*
** \fBNote:\fP Only change this setting if you know what you are doing.
*/
#endif
-
{"mix_entry_format", DT_STR, R_NONE, UL &MixEntryFormat, "%4n %c %-16s %a"},
/*
** .pp
*/
/* XXX Default values! */
-
{"pgp_decode_command", DT_STR, R_NONE, UL &PgpDecodeCommand, "" },
/*
** .pp
** ``X-Mailto-'' and the message including headers will be shown in the editor
** regardless of what ``$$edit_headers'' is set to.
**/
- {"strict_mime", DT_BOOL, R_NONE, OPTSTRICTMIME, "yes" },
- /*
- ** .pp
- ** When \fIunset\fP, non MIME-compliant messages that doesn't have any
- ** charset indication in the ``\fTContent-Type:\fP'' header field can
- ** be displayed (non MIME-compliant messages are often generated by old
- ** mailers or buggy mailers like MS Outlook Express).
- ** See also $$assumed_charset.
- ** .pp
- ** This option also replaces linear-white-space between encoded-word
- ** and *text to a single space to prevent the display of MIME-encoded
- ** ``\fTSubject:\fP'' header field from being devided into multiple lines.
- */
{"strict_threads", DT_BOOL, R_RESORT|R_RESORT_INIT|R_INDEX, OPTSTRICTTHREADS, "no" },
/*
** .pp
*/
#endif
/*--*/
+ {"strict_mime", DT_BOOL, R_NONE, OPTSTRICTMIME, "yes" },
{ NULL, -1, R_NONE, -1, NULL }
};
*/
void rfc2047_decode(char **pd)
{
- const int strict_mime = option(OPTSTRICTMIME);
-
const char *s = *pd;
char *d0, *d;
ssize_t dlen;
if (!p) {
/* no encoded words */
- if (!strict_mime) {
- ssize_t m, n;
-
- n = m_strlen(s);
- if (found_encoded && (m = lwslen(s, n)) != 0) {
- if (m != n)
- *d++ = ' ', dlen--;
- n -= m, s += m;
- }
+ ssize_t m, n;
+
+ n = m_strlen(s);
+ if (found_encoded && (m = lwslen(s, n)) != 0) {
+ if (m != n)
+ *d++ = ' ', dlen--;
+ n -= m, s += m;
+ }
+
+ if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) {
+ char *t;
- if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) {
- char *t;
-
- t = p_dupstr(s, n);
- if (mutt_convert_nonmime_string(&t) == 0) {
- d += m_strcpy(d, dlen, t);
- } else {
- d += m_strcpy(d, dlen, s);
- }
- p_delete(&t);
- break;
+ t = p_dupstr(s, n);
+ if (mutt_convert_nonmime_string(&t) == 0) {
+ d += m_strcpy(d, dlen, t);
+ } else {
+ d += m_strcpy(d, dlen, s);
}
+ p_delete(&t);
+ break;
}
+
d += m_strcpy(d, dlen, s);
break;
}
n = (p - s);
/* ignore spaces between encoded words
* and linear white spaces between encoded word and *text */
- if (!strict_mime) {
- if (found_encoded && (m = lwslen(s, n)) != 0) {
- if (m != n)
- *d++ = ' ', dlen--;
- n -= m, s += m;
- }
+ if (found_encoded && (m = lwslen(s, n)) != 0) {
+ if (m != n)
+ *d++ = ' ', dlen--;
+ n -= m, s += m;
+ }
- if ((m = n - lwsrlen(s, n)) != 0) {
- m = m_strncpy(d, dlen, s, m);
- d += m;
- dlen -= m;
- if (m != n)
- *d++ = ' ', dlen--;
- }
- } else
- if (!found_encoded || (ssize_t)strspn(s, " \t\r\n") != n) {
- n = m_strncpy(d, dlen, s, n);
- d += n;
- dlen -= n;
+ if ((m = n - lwsrlen(s, n)) != 0) {
+ m = m_strncpy(d, dlen, s, m);
+ d += m;
+ dlen -= m;
+ if (m != n)
+ *d++ = ' ', dlen--;
}
}
* Internet Gateways. So we actually decode it.
*/
- if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?"))
- rfc2047_decode (&p->value);
- else if (!option (OPTSTRICTMIME)) {
+ if (option(OPTRFC2047PARAMS) && p->value && strstr(p->value, "=?")) {
+ rfc2047_decode(&p->value);
+ } else {
if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII)
mutt_convert_nonmime_string(&p->value);
}
#include <lib-lib/lib-lib.h>
#include "recvattach.h"
-
#include "charset.h"
#include "mime.h"
s++;
for (i = 0; *s && i < ssizeof(buffer) - 1; i++, s++) {
- if (!option(OPTSTRICTMIME)) {
- /* As iso-2022-* has a characer of '"' with non-ascii state,
- * ignore it. */
- if (*s == 0x1b && i < ssizeof(buffer) - 2) {
- state_ascii = s[1] == '(' && (s[2] == 'B' || s[2] == 'J');
- }
+ /* As iso-2022-* has a characer of '"' with non-ascii state,
+ * ignore it. */
+ if (*s == 0x1b && i < ssizeof(buffer) - 2) {
+ state_ascii = s[1] == '(' && (s[2] == 'B' || s[2] == 'J');
}
if (state_ascii && *s == '"')
break;
pc = parameter_getval(ct->parameter, "charset");
if (!pc) {
parameter_setval(&ct->parameter, "charset",
- option(OPTSTRICTMIME)
- ? "us-ascii"
- : charset_getfirst(AssumedCharset));
+ charset_getfirst(AssumedCharset));
}
}
}
p = strpbrk(line, ": \t");
if (!p || *p != ':') {
- char return_path[LONG_STRING];
- time_t t;
-
/* some bogus MTAs will quote the original "From " line */
- if (!m_strncmp(">From ", line, 6))
+ if (!m_strncmp(">From ", line, 6) || !m_strncmp("From ", line, 5))
continue; /* just ignore */
- if (is_from(line, return_path, sizeof(return_path), &t)) {
- /* MH somtimes has the From_ line in the middle of the header! */
- if (hdr && !hdr->received)
- hdr->received = t - mutt_local_tz(t);
- continue;
- }
-
fseeko(f, loc, 0);
break; /* end of header */
}
#include <lib-ui/sidebar.h>
#include "mutt.h"
+#include "pattern.h"
#include "buffy.h"
#include "mx.h"
#include "mbox.h"
p_delete(&ctx->path);
p_delete(&ctx->pattern);
- if (ctx->limit_pattern)
- mutt_pattern_free (&ctx->limit_pattern);
+ pattern_list_wipe(&ctx->limit_pattern);
m_fclose(&ctx->fp);
p_clear(ctx, 1);
}
#include "curses.h"
+#include "pattern.h"
#include "mutt.h"
/* globals */
*/
regfree (&tmp->rx);
- mutt_pattern_free (&tmp->color_pattern);
+ pattern_list_wipe(&tmp->color_pattern);
p_delete(&tmp->pattern);
p_delete(l);
}
#include "menu.h"
#include "mutt.h"
+#include "pattern.h"
#include "alias.h"
#include "sort.h"
#include "recvattach.h"
int tabs;
} ENTER_STATE;
+#define mutt_new_enter_state() p_new(ENTER_STATE, 1)
+
void mutt_free_enter_state (ENTER_STATE **);
int mutt_enter_string (char *buf, size_t buflen, int y, int x, int flags);
int _mutt_enter_string (char *, size_t, int, int, int, int, char ***, int *,
HEADER *sort_key;
} THREAD;
-
-/* flag to mutt_pattern_comp() */
-#define M_FULL_MSG (1<<0) /* enable body and header matching */
-
-typedef enum {
- M_MATCH_FULL_ADDRESS = 1
-} pattern_exec_flag;
-
-typedef struct pattern_t {
- short op;
- unsigned int not : 1;
- unsigned int alladdr : 1;
- unsigned int stringmatch : 1;
- int min;
- int max;
- struct pattern_t *next;
- struct pattern_t *child; /* arguments to logical op */
- char* str;
- regex_t *rx;
-} pattern_t;
-
typedef struct compress_info compress_info;
+typedef struct pattern_t pattern_t;
typedef struct {
char *path;
#include <lib-lib/lib-lib.h>
#include <lib-mime/mime.h>
+#include <lib-crypt/crypt.h>
#include <lib-ui/enter.h>
#include <lib-ui/curses.h>
#include <lib-mx/mx.h>
+#include <imap/imap.h>
-#include "mutt.h"
+#include "pattern.h"
#include "alias.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},
#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)
{
return 0;
}
-static struct pattern_flags *lookup_tag (char tag)
+static const struct pattern_flags *lookup_tag (char tag)
{
int i;
return s;
}
-void mutt_pattern_free (pattern_t ** pat)
-{
- pattern_t *tmp;
-
- while (*pat) {
- tmp = *pat;
- *pat = (*pat)->next;
-
- if (tmp->rx) {
- regfree (tmp->rx);
- p_delete(&tmp->rx);
- }
- p_delete(&tmp->str);
- if (tmp->child)
- mutt_pattern_free (&tmp->child);
- p_delete(&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;
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;
/* 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;
}
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 =
--- /dev/null
+/*
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Copyright © 2006 Pierre Habouzit
+ */
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ */
+
+#ifndef MUTT_PATTERN_H
+#define MUTT_PATTERN_H
+
+#include <lib-lib/lib-lib.h>
+
+/* flag to mutt_pattern_comp() */
+#define M_FULL_MSG (1<<0) /* enable body and header matching */
+
+typedef enum {
+ M_MATCH_FULL_ADDRESS = 1
+} pattern_exec_flag;
+
+struct pattern_t {
+ struct pattern_t *next;
+
+ short op;
+ unsigned not : 1;
+ unsigned alladdr : 1;
+ unsigned stringmatch : 1;
+ int min;
+ int max;
+ struct pattern_t *child; /* arguments to logical op */
+ char* str;
+ regex_t *rx;
+};
+
+DO_INIT(pattern_t, pattern);
+void pattern_wipe(pattern_t *);
+DO_NEW(pattern_t, pattern);
+DO_DELETE(pattern_t, pattern);
+
+DO_SLIST(pattern_t, pattern, pattern_delete);
+
+int mutt_pattern_func (int, char *);
+int mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
+ CONTEXT * ctx, HEADER * h);
+pattern_t *mutt_pattern_comp(const char *s, int flags, BUFFER * err);
+void mutt_check_simple (char *s, ssize_t len, const char *simple);
+
+#endif
int mutt_parse_score (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_unscore (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_unhook (BUFFER *, BUFFER *, unsigned long, BUFFER *);
-int mutt_pattern_func (int, char *);
int mutt_query_variables (string_list_t * queries);
int _mutt_save_message (HEADER *, CONTEXT *, int, int, int);
int mutt_save_message (HEADER *, int, int, int, int *);
void mutt_to_base64 (unsigned char *, const unsigned char *, ssize_t, ssize_t);
int mutt_from_base64 (char *, const char *);
-#define new_pattern() p_new(pattern_t, 1)
-#define mutt_new_enter_state() p_new(ENTER_STATE, 1)
-
-int mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
- CONTEXT * ctx, HEADER * h);
-pattern_t *mutt_pattern_comp ( /* const */ char *s, int flags, BUFFER * err);
-void mutt_check_simple (char *s, ssize_t len, const char *simple);
-void mutt_pattern_free (pattern_t ** pat);
-
void ci_bounce_message (HEADER *, int *);
int ci_send_message (int, HEADER *, char *, CONTEXT *, HEADER *);
#include "mutt.h"
#include "sort.h"
+#include "pattern.h"
typedef struct score_t {
char *str;
for (tmp = Score; tmp;) {
last = tmp;
tmp = tmp->next;
- mutt_pattern_free (&last->pat);
+ pattern_list_wipe(&last->pat);
p_delete(&last);
}
Score = NULL;
last->next = tmp->next;
else
Score = tmp->next;
- mutt_pattern_free (&tmp->pat);
+ pattern_list_wipe(&tmp->pat);
p_delete(&tmp);
/* there should only be one score per pattern, so we can stop here */
break;