X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=muttlib.c;h=d5bd3b7ffca243a5e65d82bc22d74d5a3bfbc088;hp=3e96ae9c79f65802a1bc9a3c11b3909c5276b86d;hb=452ffdd4bbcd8f2dd9e4811c115824b556814ebb;hpb=df70e07e24add1869bcc9b7af2277d9d0c09a281 diff --git a/muttlib.c b/muttlib.c index 3e96ae9..d5bd3b7 100644 --- a/muttlib.c +++ b/muttlib.c @@ -1,20 +1,11 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2000 Michael R. Elkins * Copyright (C) 1999-2000 Thomas Roessler - * - * 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 @@ -22,20 +13,30 @@ #endif #include "mutt.h" +#include "ascii.h" +#include "buffer.h" +#include "enter.h" #include "mutt_curses.h" #include "mime.h" -#include "mailbox.h" #include "mx.h" #include "url.h" +#include "attach.h" #include "reldate.h" +#include "version.h" #ifdef USE_IMAP #include "imap.h" +#include "imap/mx_imap.h" #endif #include "mutt_crypt.h" +#include "lib/mem.h" +#include "lib/intl.h" +#include "lib/str.h" +#include "lib/debug.h" + #include #include #include @@ -50,7 +51,7 @@ BODY *mutt_new_body (void) { - BODY *p = (BODY *) safe_calloc (1, sizeof (BODY)); + BODY *p = (BODY *) mem_calloc (1, sizeof (BODY)); p->disposition = DISPATTACH; p->use_disp = 1; @@ -64,7 +65,7 @@ BODY *mutt_new_body (void) * Renamed to mutt_adv_mktemp so I only have to change where it's * called, and not all possible cases. */ -void mutt_adv_mktemp (char *s, size_t l) +void mutt_adv_mktemp (const char* dir, char *s, size_t l) { char buf[_POSIX_PATH_MAX]; char tmp[_POSIX_PATH_MAX]; @@ -72,7 +73,7 @@ void mutt_adv_mktemp (char *s, size_t l) size_t sl; struct stat sb; - strfcpy (buf, NONULL (Tempdir), sizeof (buf)); + strfcpy (buf, dir && *dir ? dir : NONULL (Tempdir), sizeof (buf)); mutt_expand_path (buf, sizeof (buf)); if (s[0] == '\0') { snprintf (s, l, "%s/muttXXXXXX", buf); @@ -90,7 +91,7 @@ void mutt_adv_mktemp (char *s, size_t l) mktemp (s); if (period != NULL) { *period = '.'; - sl = mutt_strlen (s); + sl = str_len (s); strfcpy (s + sl, period, l - sl); } } @@ -116,7 +117,7 @@ int mutt_copy_body (FILE * fp, BODY ** tgt, BODY * src) tmp[0] = '\0'; } - mutt_adv_mktemp (tmp, sizeof (tmp)); + mutt_adv_mktemp (NULL, tmp, sizeof (tmp)); if (mutt_save_attachment (fp, src, tmp, 0, NULL) == -1) return -1; @@ -127,19 +128,19 @@ int mutt_copy_body (FILE * fp, BODY ** tgt, BODY * src) b->parts = NULL; b->next = NULL; - b->filename = safe_strdup (tmp); + b->filename = str_dup (tmp); b->use_disp = use_disp; b->unlink = 1; if (mutt_is_text_part (b)) b->noconv = 1; - b->xtype = safe_strdup (b->xtype); - b->subtype = safe_strdup (b->subtype); - b->form_name = safe_strdup (b->form_name); - b->filename = safe_strdup (b->filename); - b->d_filename = safe_strdup (b->d_filename); - b->description = safe_strdup (b->description); + b->xtype = str_dup (b->xtype); + b->subtype = str_dup (b->subtype); + b->form_name = str_dup (b->form_name); + b->filename = str_dup (b->filename); + b->d_filename = str_dup (b->d_filename); + b->description = str_dup (b->description); /* * we don't seem to need the HEADER structure currently. @@ -153,8 +154,8 @@ int mutt_copy_body (FILE * fp, BODY ** tgt, BODY * src) for (par = b->parameter, ppar = &b->parameter; par; ppar = &(*ppar)->next, par = par->next) { *ppar = mutt_new_parameter (); - (*ppar)->attribute = safe_strdup (par->attribute); - (*ppar)->value = safe_strdup (par->value); + (*ppar)->attribute = str_dup (par->attribute); + (*ppar)->value = str_dup (par->value); } mutt_stamp_attachment (b); @@ -175,20 +176,18 @@ void mutt_free_body (BODY ** p) if (b->parameter) mutt_free_parameter (&b->parameter); if (b->unlink && b->filename) { - dprint (1, (debugfile, "mutt_free_body: Unlinking %s.\n", b->filename)); + debug_print (1, ("unlinking %s.\n", b->filename)); unlink (b->filename); } else if (b->filename) - dprint (1, - (debugfile, "mutt_free_body: Not unlinking %s.\n", - b->filename)); + debug_print (1, ("not unlinking %s.\n", b->filename)); - FREE (&b->filename); - FREE (&b->content); - FREE (&b->xtype); - FREE (&b->subtype); - FREE (&b->description); - FREE (&b->form_name); + mem_free (&b->filename); + mem_free (&b->content); + mem_free (&b->xtype); + mem_free (&b->subtype); + mem_free (&b->description); + mem_free (&b->form_name); if (b->hdr) { /* Don't free twice (b->hdr->content = b->parts) */ @@ -199,7 +198,7 @@ void mutt_free_body (BODY ** p) if (b->parts) mutt_free_body (&b->parts); - FREE (&b); + mem_free (&b); } *p = 0; @@ -211,46 +210,15 @@ void mutt_free_parameter (PARAMETER ** p) PARAMETER *o; while (t) { - FREE (&t->attribute); - FREE (&t->value); + mem_free (&t->attribute); + mem_free (&t->value); o = t; t = t->next; - FREE (&o); + mem_free (&o); } *p = 0; } -LIST *mutt_add_list (LIST * head, const char *data) -{ - LIST *tmp; - - for (tmp = head; tmp && tmp->next; tmp = tmp->next); - if (tmp) { - tmp->next = safe_malloc (sizeof (LIST)); - tmp = tmp->next; - } - else - head = tmp = safe_malloc (sizeof (LIST)); - - tmp->data = safe_strdup (data); - tmp->next = NULL; - return head; -} - -void mutt_free_list (LIST ** list) -{ - LIST *p; - - if (!list) - return; - while (*list) { - p = *list; - *list = (*list)->next; - FREE (&p->data); - FREE (&p); - } -} - HEADER *mutt_dup_header (HEADER * h) { HEADER *hnew; @@ -266,23 +234,23 @@ void mutt_free_header (HEADER ** h) return; mutt_free_envelope (&(*h)->env); mutt_free_body (&(*h)->content); - FREE (&(*h)->maildir_flags); - FREE (&(*h)->tree); - FREE (&(*h)->path); + mem_free (&(*h)->maildir_flags); + mem_free (&(*h)->tree); + mem_free (&(*h)->path); #ifdef MIXMASTER mutt_free_list (&(*h)->chain); #endif #if defined USE_POP || defined USE_IMAP || defined USE_NNTP - FREE (&(*h)->data); + mem_free (&(*h)->data); #endif - FREE (h); + mem_free (h); } /* returns true if the header contained in "s" is in list "t" */ int mutt_matches_ignore (const char *s, LIST * t) { for (; t; t = t->next) { - if (!ascii_strncasecmp (s, t->data, mutt_strlen (t->data)) + if (!ascii_strncasecmp (s, t->data, str_len (t->data)) || *t->data == '*') return 1; } @@ -368,10 +336,9 @@ char *_mutt_expand_path (char *s, size_t slen, int rx) case '+': { #ifdef USE_IMAP - /* if folder = {host} or imap[s]://host/: don't append slash */ - if (mx_is_imap (NONULL (Maildir)) && - (Maildir[strlen (Maildir) - 1] == '}' || - Maildir[strlen (Maildir) - 1] == '/')) + /* if folder = imap[s]://host/: don't append slash */ + if (imap_is_magic (NONULL (Maildir), NULL) == M_IMAP && + Maildir[str_len (Maildir) - 1] == '/') strfcpy (p, NONULL (Maildir), sizeof (p)); else #endif @@ -463,13 +430,6 @@ char *_mutt_expand_path (char *s, size_t slen, int rx) } while (recurse); -#ifdef USE_IMAP - /* Rewrite IMAP path in canonical form - aids in string comparisons of - * folders. May possibly fail, in which case s should be the same. */ - if (mx_is_imap (s)) - imap_expand_path (s, slen); -#endif - return (s); } @@ -503,7 +463,7 @@ char *mutt_gecos_name (char *dest, size_t destlen, struct passwd *pw) else strfcpy (dest, pw->pw_gecos, destlen); - pwnl = strlen (pw->pw_name); + pwnl = str_len (pw->pw_name); for (idx = 0; dest[idx]; idx++) { if (dest[idx] == '&') { @@ -539,14 +499,14 @@ void mutt_set_parameter (const char *attribute, const char *value, for (q = *p; q; q = q->next) { if (ascii_strcasecmp (attribute, q->attribute) == 0) { - mutt_str_replace (&q->value, value); + str_replace (&q->value, value); return; } } q = mutt_new_parameter (); - q->attribute = safe_strdup (attribute); - q->value = safe_strdup (value); + q->attribute = str_dup (attribute); + q->value = str_dup (value); q->next = *p; *p = q; } @@ -629,34 +589,79 @@ void mutt_free_envelope (ENVELOPE ** p) rfc822_free_address (&(*p)->reply_to); rfc822_free_address (&(*p)->mail_followup_to); - FREE (&(*p)->list_post); - FREE (&(*p)->subject); + mem_free (&(*p)->list_post); + mem_free (&(*p)->subject); /* real_subj is just an offset to subject and shouldn't be freed */ - FREE (&(*p)->message_id); - FREE (&(*p)->supersedes); - FREE (&(*p)->date); - FREE (&(*p)->x_label); - FREE (&(*p)->organization); + mem_free (&(*p)->message_id); + mem_free (&(*p)->supersedes); + mem_free (&(*p)->date); + mem_free (&(*p)->x_label); + mem_free (&(*p)->organization); #ifdef USE_NNTP - FREE (&(*p)->newsgroups); - FREE (&(*p)->xref); - FREE (&(*p)->followup_to); - FREE (&(*p)->x_comment_to); + mem_free (&(*p)->newsgroups); + mem_free (&(*p)->xref); + mem_free (&(*p)->followup_to); + mem_free (&(*p)->x_comment_to); #endif mutt_buffer_free (&(*p)->spam); mutt_free_list (&(*p)->references); mutt_free_list (&(*p)->in_reply_to); mutt_free_list (&(*p)->userhdrs); - FREE (p); + mem_free (p); +} + +/* move all the headers from extra not present in base into base */ +void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra) +{ + /* copies each existing element if necessary, and sets the element + * to NULL in the source so that mutt_free_envelope doesn't leave us + * with dangling pointers. */ +#define MOVE_ELEM(h) if (!base->h) { base->h = (*extra)->h; (*extra)->h = NULL; } + MOVE_ELEM(return_path); + MOVE_ELEM(from); + MOVE_ELEM(to); + MOVE_ELEM(cc); + MOVE_ELEM(bcc); + MOVE_ELEM(sender); + MOVE_ELEM(reply_to); + MOVE_ELEM(mail_followup_to); + MOVE_ELEM(list_post); + MOVE_ELEM(message_id); + MOVE_ELEM(supersedes); + MOVE_ELEM(date); + MOVE_ELEM(x_label); + if (!base->refs_changed) { + MOVE_ELEM(references); + } + if (!base->irt_changed) { + MOVE_ELEM(in_reply_to); + } + /* real_subj is subordinate to subject */ + if (!base->subject) { + base->subject = (*extra)->subject; + base->real_subj = (*extra)->real_subj; + (*extra)->subject = NULL; + (*extra)->real_subj = NULL; + } + /* spam and user headers should never be hashed, and the new envelope may + * have better values. Use new versions regardless. */ + mutt_buffer_free (&base->spam); + mutt_free_list (&base->userhdrs); + MOVE_ELEM(spam); + MOVE_ELEM(userhdrs); +#undef MOVE_ELEM + + mutt_free_envelope(extra); } void _mutt_mktemp (char *s, const char *src, int line) { - snprintf (s, _POSIX_PATH_MAX, "%s/mutt-%s-%d-%d-%d", NONULL (Tempdir), - NONULL (Hostname), (int) getuid (), (int) getpid (), Counter++); - dprint (1, - (debugfile, "%s:%d: mutt_mktemp returns \"%s\".\n", src, line, s)); + + snprintf (s, _POSIX_PATH_MAX, "%s/muttng-%s-%d-%d-%d-%x%x", NONULL (Tempdir), + NONULL (Hostname), (int) getuid (), (int) getpid (), Counter++, + (unsigned int) rand(), (unsigned int) rand()); + debug_print (1, ("%s:%d: mutt_mktemp returns \"%s\".\n", src, line, s)); unlink (s); } @@ -667,9 +672,9 @@ void mutt_free_alias (ALIAS ** p) while (*p) { t = *p; *p = (*p)->next; - FREE (&t->name); + mem_free (&t->name); rfc822_free_address (&t->addr); - FREE (&t); + mem_free (&t); } } @@ -714,15 +719,15 @@ void mutt_pretty_mailbox (char *s) } *q = 0; - if (mutt_strncmp (s, Maildir, (len = mutt_strlen (Maildir))) == 0 && + if (str_ncmp (s, Maildir, (len = str_len (Maildir))) == 0 && s[len] == '/') { *s++ = '='; - memmove (s, s + len, mutt_strlen (s + len) + 1); + memmove (s, s + len, str_len (s + len) + 1); } - else if (mutt_strncmp (s, Homedir, (len = mutt_strlen (Homedir))) == 0 && + else if (str_ncmp (s, Homedir, (len = str_len (Homedir))) == 0 && s[len] == '/') { *s++ = '~'; - memmove (s, s + len - 1, mutt_strlen (s + len - 1) + 1); + memmove (s, s + len - 1, str_len (s + len - 1) + 1); } } @@ -762,7 +767,7 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, size_t slen; int found = 0; - slen = mutt_strlen (src); + slen = str_len (src); destlen--; for (p = fmt, d = dest; destlen && *p; p++) { @@ -794,8 +799,8 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, *d = '\0'; if (!found && destlen > 0) { - safe_strcat (dest, destlen, " "); - safe_strcat (dest, destlen, src); + str_cat (dest, destlen, " "); + str_cat (dest, destlen, src); } } @@ -820,16 +825,16 @@ int mutt_check_overwrite (const char *attname, const char *path, (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), _("yna"))) { case 3: /* all */ - mutt_str_replace (directory, fname); + str_replace (directory, fname); break; case 1: /* yes */ - FREE (directory); + mem_free (directory); break; case -1: /* abort */ - FREE (directory); + mem_free (directory); return -1; case 2: /* no */ - FREE (directory); + mem_free (directory); return 1; } } @@ -880,7 +885,7 @@ void mutt_save_path (char *d, size_t dsize, ADDRESS * a) if ((p = strpbrk (d, "%@"))) *p = 0; } - mutt_strlower (d); + str_tolower (d); } else *d = 0; @@ -914,7 +919,7 @@ int mutt_skipchars (const char *s, const char *c) ret++; s++; } - return (mutt_strlen (p)); + return (str_len (p)); } void mutt_FormatString (char *dest, /* output buffer */ @@ -1014,7 +1019,7 @@ void mutt_FormatString (char *dest, /* output buffer */ if (count > col) { count -= col; /* how many columns left on this line */ mutt_FormatString (buf, sizeof (buf), src, callback, data, flags); - wid = mutt_strlen (buf); + wid = str_len (buf); if (count > wid) { count -= wid; /* how many chars to pad */ memset (wptr, ch, count); @@ -1063,7 +1068,7 @@ void mutt_FormatString (char *dest, /* output buffer */ data, flags); if (tolower) - mutt_strlower (buf); + str_tolower (buf); if (nodots) { char *p = buf; @@ -1072,7 +1077,7 @@ void mutt_FormatString (char *dest, /* output buffer */ *p = '_'; } - if ((len = mutt_strlen (buf)) + wlen > destlen) + if ((len = str_len (buf)) + wlen > destlen) len = (destlen - wlen > 0) ? (destlen - wlen) : 0; memcpy (wptr, buf, len); @@ -1111,7 +1116,7 @@ void mutt_FormatString (char *dest, /* output buffer */ } else { unsigned int bar = mutt_skipchars (src, "%\\"); - char *bar2 = safe_malloc (bar + 1); + char *bar2 = mem_malloc (bar + 1); strfcpy (bar2, src, bar + 1); while (bar--) { @@ -1119,7 +1124,7 @@ void mutt_FormatString (char *dest, /* output buffer */ wlen++; } col += mutt_strwidth (bar2); - FREE (&bar2); + mem_free (&bar2); } } *wptr = 0; @@ -1143,17 +1148,17 @@ FILE *mutt_open_read (const char *path, pid_t * thepid) FILE *f; struct stat s; - int len = mutt_strlen (path); + int len = str_len (path); if (path[len - 1] == '|') { /* read from a pipe */ - char *s = safe_strdup (path); + char *s = str_dup (path); s[len - 1] = 0; mutt_endwin (NULL); *thepid = mutt_create_filter (s, NULL, &f, NULL); - FREE (&s); + mem_free (&s); } else { if (stat (path, &s) < 0) @@ -1194,16 +1199,10 @@ int mutt_save_confirm (const char *s, struct stat *st) } #endif - if (stat (s, st) != -1) { - if (magic == -1) { - mutt_error (_("%s is not a mailbox!"), s); - return 1; - } - + if (magic > 0 && !mx_access (s, W_OK)) { if (option (OPTCONFIRMAPPEND) && - (!TrashPath || (mutt_strcmp (s, TrashPath) != 0))) + (!TrashPath || (str_cmp (s, TrashPath) != 0))) { /* if we're appending to the trash, there's no point in asking */ - { snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s); if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) ret = 1; @@ -1211,6 +1210,13 @@ int mutt_save_confirm (const char *s, struct stat *st) ret = -1; } } + + if (stat (s, st) != -1) { + if (magic == -1) { + mutt_error (_("%s is not a mailbox!"), s); + return 1; + } + } else { #ifdef USE_IMAP if (magic != M_IMAP) @@ -1239,81 +1245,6 @@ int mutt_save_confirm (const char *s, struct stat *st) return (ret); } -void state_prefix_putc (char c, STATE * s) -{ - if (s->flags & M_PENDINGPREFIX) { - int i; - - i = strlen (Quotebuf); - Quotebuf[i++] = c; - Quotebuf[i] = '\0'; - if (i == sizeof (Quotebuf) - 1 || c == '\n') { - char buf[2 * SHORT_STRING]; - int j = 0, offset = 0; - regmatch_t pmatch[1]; - - state_reset_prefix (s); - while (regexec - ((regex_t *) QuoteRegexp.rx, &Quotebuf[offset], 1, pmatch, - 0) == 0) - offset += pmatch->rm_eo; - - if (!option (OPTQUOTEEMPTY) && Quotebuf[offset] == '\n') { - buf[0] = '\n'; - buf[1] = '\0'; - } - else if (option (OPTQUOTEQUOTED) && offset) { - for (i = 0; i < offset; i++) - if (Quotebuf[i] != ' ') - j = i; - strncpy (buf, Quotebuf, j + 1); - strcpy (buf + j + 1, Quotebuf + j); - } - else - snprintf (buf, sizeof (buf), "%s%s", NONULL (s->prefix), Quotebuf); - - state_puts (buf, s); - } - } - else - state_putc (c, s); - - if (c == '\n') { - state_set_prefix (s); - Quotebuf[0] = '\0'; - } -} - -int state_printf (STATE * s, const char *fmt, ...) -{ - int rv; - va_list ap; - - va_start (ap, fmt); - rv = vfprintf (s->fpout, fmt, ap); - va_end (ap); - - return rv; -} - -void state_mark_attach (STATE * s) -{ - if ((s->flags & M_DISPLAY) && !mutt_strcmp (Pager, "builtin")) - state_puts (AttachmentMarker, s); -} - -void state_attach_puts (const char *t, STATE * s) -{ - if (*t != '\n') - state_mark_attach (s); - while (*t) { - state_putc (*t, s); - if (*t++ == '\n' && *t) - if (*t != '\n') - state_mark_attach (s); - } -} - void mutt_display_sanitize (char *s) { for (; *s; s++) { @@ -1330,85 +1261,6 @@ void mutt_sleep (short s) sleep (s); } -/* - * Creates and initializes a BUFFER*. If passed an existing BUFFER*, - * just initializes. Frees anything already in the buffer. - * - * Disregards the 'destroy' flag, which seems reserved for caller. - * This is bad, but there's no apparent protocol for it. - */ -BUFFER *mutt_buffer_init (BUFFER * b) -{ - if (!b) { - b = safe_malloc (sizeof (BUFFER)); - if (!b) - return NULL; - } - else { - safe_free (b->data); - } - memset (b, 0, sizeof (BUFFER)); - return b; -} - -/* - * Creates and initializes a BUFFER*. If passed an existing BUFFER*, - * just initializes. Frees anything already in the buffer. Copies in - * the seed string. - * - * Disregards the 'destroy' flag, which seems reserved for caller. - * This is bad, but there's no apparent protocol for it. - */ -BUFFER *mutt_buffer_from (BUFFER * b, char *seed) -{ - if (!seed) - return NULL; - - b = mutt_buffer_init (b); - b->data = safe_strdup (seed); - b->dsize = mutt_strlen (seed); - b->dptr = (char *) b->data + b->dsize; - return b; -} - -void mutt_buffer_addstr (BUFFER * buf, const char *s) -{ - mutt_buffer_add (buf, s, mutt_strlen (s)); -} - -void mutt_buffer_addch (BUFFER * buf, char c) -{ - mutt_buffer_add (buf, &c, 1); -} - -void mutt_buffer_free (BUFFER ** p) -{ - if (!p || !*p) - return; - - FREE (&(*p)->data); - /* dptr is just an offset to data and shouldn't be freed */ - FREE (p); -} - -/* dynamically grows a BUFFER to accomodate s, in increments of 128 bytes. - * Always one byte bigger than necessary for the null terminator, and - * the buffer is always null-terminated */ -void mutt_buffer_add (BUFFER * buf, const char *s, size_t len) -{ - size_t offset; - - if (buf->dptr + len + 1 > buf->data + buf->dsize) { - offset = buf->dptr - buf->data; - buf->dsize += len < 128 ? 128 : len + 1; - safe_realloc ((void **) &buf->data, buf->dsize); - buf->dptr = buf->data + offset; - } - memcpy (buf->dptr, s, len); - buf->dptr += len; - *(buf->dptr) = '\0'; -} - /* Decrease a file's modification time by 1 second */ time_t mutt_decrease_mtime (const char *f, struct stat *st) @@ -1433,49 +1285,20 @@ time_t mutt_decrease_mtime (const char *f, struct stat *st) return mtime; } -const char *mutt_make_version (void) +const char *mutt_make_version (int full) { static char vstring[STRING]; - snprintf (vstring, sizeof (vstring), "Mutt-ng %s (%s)", - MUTT_VERSION, ReleaseDate); + if (full) + snprintf (vstring, sizeof (vstring), "Mutt-ng %s-r%s (based " + "on Mutt 1.5.10/%s)", MUTT_VERSION, MUTT_REVISION, + ReleaseDate); + else + snprintf (vstring, sizeof (vstring), "mutt-ng/%s-r%s", + MUTT_VERSION, MUTT_REVISION); return vstring; } -REGEXP *mutt_compile_regexp (const char *s, int flags) -{ - REGEXP *pp = safe_calloc (sizeof (REGEXP), 1); - - pp->pattern = safe_strdup (s); - pp->rx = safe_calloc (sizeof (regex_t), 1); - if (REGCOMP (pp->rx, NONULL (s), flags) != 0) - mutt_free_regexp (&pp); - - return pp; -} - -void mutt_free_regexp (REGEXP ** pp) -{ - FREE (&(*pp)->pattern); - regfree ((*pp)->rx); - FREE (&(*pp)->rx); - FREE (pp); -} - -void mutt_free_rx_list (RX_LIST ** list) -{ - RX_LIST *p; - - if (!list) - return; - while (*list) { - p = *list; - *list = (*list)->next; - mutt_free_regexp (&p->rx); - FREE (&p); - } -} - void mutt_free_spam_list (SPAM_LIST ** list) { SPAM_LIST *p; @@ -1485,27 +1308,10 @@ void mutt_free_spam_list (SPAM_LIST ** list) while (*list) { p = *list; *list = (*list)->next; - mutt_free_regexp (&p->rx); - safe_free (&p->template); - FREE (&p); - } -} - -int mutt_match_rx_list (const char *s, RX_LIST * l) -{ - if (!s) - return 0; - - for (; l; l = l->next) { - if (regexec (l->rx->rx, s, (size_t) 0, (regmatch_t *) 0, (int) 0) == 0) { - dprint (5, - (debugfile, "mutt_match_rx_list: %s matches %s\n", s, - l->rx->pattern)); - return 1; - } + rx_free (&p->rx); + mem_free(&p->template); + mem_free(&p); } - - return 0; } int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x) @@ -1523,7 +1329,7 @@ int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x) for (; l; l = l->next) { /* If this pattern needs more matches, expand pmatch. */ if (l->nmatch > nmatch) { - safe_realloc (&pmatch, l->nmatch * sizeof (regmatch_t)); + mem_realloc (&pmatch, l->nmatch * sizeof (regmatch_t)); nmatch = l->nmatch; } @@ -1531,12 +1337,7 @@ int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x) if (regexec (l->rx->rx, s, (size_t) l->nmatch, (regmatch_t *) pmatch, (int) 0) == 0) { - dprint (5, - (debugfile, "mutt_match_spam_list: %s matches %s\n", s, - l->rx->pattern)); - dprint (5, - (debugfile, "mutt_match_spam_list: %d subs\n", - l->rx->rx->re_nsub)); + debug_print (5, ("%s matches %s\n%d subst", s, l->rx->pattern, l->rx->rx->re_nsub)); /* Copy template into text, with substitutions. */ for (p = l->template; *p;) { @@ -1552,10 +1353,118 @@ int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x) } } text[tlen] = '\0'; - dprint (5, (debugfile, "mutt_match_spam_list: \"%s\"\n", text)); + debug_print (5, ("\"%s\"\n", text)); return 1; } } return 0; } + +int mutt_cmp_header (const HEADER * h1, const HEADER * h2) { + if (h1 && h2) { + if (h1->received != h2->received || + h1->date_sent != h2->date_sent || + h1->content->length != h2->content->length || + h1->lines != h2->lines || + h1->zhours != h2->zhours || + h1->zminutes != h2->zminutes || + h1->zoccident != h2->zoccident || + h1->mime != h2->mime || + !mutt_cmp_env (h1->env, h2->env) || + !mutt_cmp_body (h1->content, h2->content)) + return (0); + else + return (1); + } + else { + if (h1 == NULL && h2 == NULL) + return (1); + else + return (0); + } +} + +/* return 1 if address lists are strictly identical */ +int mutt_cmp_addr (const ADDRESS * a, const ADDRESS * b) +{ + while (a && b) { + if (str_cmp (a->mailbox, b->mailbox) || + str_cmp (a->personal, b->personal)) + return (0); + + a = a->next; + b = b->next; + } + if (a || b) + return (0); + + return (1); +} + +int mutt_cmp_list (const LIST * a, const LIST * b) +{ + while (a && b) { + if (str_cmp (a->data, b->data)) + return (0); + + a = a->next; + b = b->next; + } + if (a || b) + return (0); + + return (1); +} + +int mutt_cmp_env (const ENVELOPE * e1, const ENVELOPE * e2) +{ + if (e1 && e2) { + if (str_cmp (e1->message_id, e2->message_id) || + str_cmp (e1->subject, e2->subject) || + !mutt_cmp_list (e1->references, e2->references) || + !mutt_cmp_addr (e1->from, e2->from) || + !mutt_cmp_addr (e1->sender, e2->sender) || + !mutt_cmp_addr (e1->reply_to, e2->reply_to) || + !mutt_cmp_addr (e1->to, e2->to) || + !mutt_cmp_addr (e1->cc, e2->cc) || + !mutt_cmp_addr (e1->return_path, e2->return_path)) + return (0); + else + return (1); + } + else { + if (e1 == NULL && e2 == NULL) + return (1); + else + return (0); + } +} + +int mutt_cmp_param (const PARAMETER * p1, const PARAMETER * p2) +{ + while (p1 && p2) { + if (str_cmp (p1->attribute, p2->attribute) || + str_cmp (p1->value, p2->value)) + return (0); + + p1 = p1->next; + p2 = p2->next; + } + if (p1 || p2) + return (0); + + return (1); +} + +int mutt_cmp_body (const BODY * b1, const BODY * b2) +{ + if (b1->type != b2->type || + b1->encoding != b2->encoding || + str_cmp (b1->subtype, b2->subtype) || + str_cmp (b1->description, b2->description) || + !mutt_cmp_param (b1->parameter, b2->parameter) || + b1->length != b2->length) + return (0); + return (1); +}