X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=muttlib.c;h=04c0b3a28ff15fecb9443da0947b9e9c51637600;hp=0340d20d67a4ad9987de509e74056abd0c50238f;hb=5e6273c09929249ee7a850934bf12fd03439d923;hpb=079475507f097b263fcd3037c8ee10f4b0dae325 diff --git a/muttlib.c b/muttlib.c index 0340d20..04c0b3a 100644 --- a/muttlib.c +++ b/muttlib.c @@ -1,41 +1,43 @@ /* + * 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 # include "config.h" #endif +#include +#include +#include +#include +#include +#include + #include "mutt.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/debug.h" + #include #include #include @@ -48,10 +50,12 @@ #include #include +#define SW (option(OPTMBOXPANE)?SidebarWidth:0) + BODY *mutt_new_body (void) { - BODY *p = (BODY *) safe_calloc (1, sizeof (BODY)); - + BODY *p = p_new(BODY, 1); + p->disposition = DISPATTACH; p->use_disp = 1; return (p); @@ -64,24 +68,22 @@ 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]; char *period; size_t sl; struct stat sb; - - strfcpy (buf, NONULL (Tempdir), sizeof (buf)); + + m_strcpy(buf, sizeof(buf), m_strisempty(dir) ? NONULL(Tempdir) : dir); mutt_expand_path (buf, sizeof (buf)); - if (s[0] == '\0') - { + if (s[0] == '\0') { snprintf (s, l, "%s/muttXXXXXX", buf); mktemp (s); } - else - { - strfcpy (tmp, s, sizeof (tmp)); + else { + m_strcpy(tmp, sizeof(tmp), s); mutt_sanitize_filename (tmp, 1); snprintf (s, l, "%s/%s", buf, tmp); if (lstat (s, &sb) == -1 && errno == ENOENT) @@ -90,235 +92,195 @@ void mutt_adv_mktemp (char *s, size_t l) *period = 0; snprintf (s, l, "%s/%s.XXXXXX", buf, tmp); mktemp (s); - if (period != NULL) - { + if (period != NULL) { *period = '.'; - sl = mutt_strlen(s); - strfcpy(s + sl, period, l - sl); + sl = m_strlen(s); + m_strcpy(s + sl, l - sl, period); } } } /* create a send-mode duplicate from a receive-mode body */ -int mutt_copy_body (FILE *fp, BODY **tgt, BODY *src) +int mutt_copy_body (FILE * fp, BODY ** tgt, BODY * src) { char tmp[_POSIX_PATH_MAX]; BODY *b; PARAMETER *par, **ppar; - + short use_disp; - if (src->filename) - { + if (src->filename) { use_disp = 1; - strfcpy (tmp, src->filename, sizeof (tmp)); + m_strcpy(tmp, sizeof(tmp), src->filename); } - else - { + else { use_disp = 0; 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; - + *tgt = mutt_new_body (); b = *tgt; memcpy (b, src, sizeof (BODY)); b->parts = NULL; - b->next = NULL; + b->next = NULL; - b->filename = safe_strdup (tmp); + b->filename = m_strdup(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 = m_strdup(b->xtype); + b->subtype = m_strdup(b->subtype); + b->form_name = m_strdup(b->form_name); + b->filename = m_strdup(b->filename); + b->d_filename = m_strdup(b->d_filename); + b->description = m_strdup(b->description); /* * we don't seem to need the HEADER structure currently. * XXX - this may change in the future */ - if (b->hdr) b->hdr = NULL; - + if (b->hdr) + b->hdr = NULL; + /* copy parameters */ - for (par = b->parameter, ppar = &b->parameter; par; ppar = &(*ppar)->next, par = par->next) - { + 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 = m_strdup(par->attribute); + (*ppar)->value = m_strdup(par->value); } mutt_stamp_attachment (b); - + return 0; } -void mutt_free_body (BODY **p) +void mutt_free_body (BODY ** p) { BODY *a = *p, *b; - while (a) - { + while (a) { b = a; - a = a->next; + a = a->next; if (b->parameter) mutt_free_parameter (&b->parameter); - if (b->unlink && b->filename) - { - dprint (1, (debugfile, "mutt_free_body: Unlinking %s.\n", b->filename)); + if (b->unlink && 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)); + else if (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); + p_delete(&b->filename); + p_delete(&b->content); + p_delete(&b->xtype); + p_delete(&b->subtype); + p_delete(&b->description); + p_delete(&b->form_name); - if (b->hdr) - { + if (b->hdr) { /* Don't free twice (b->hdr->content = b->parts) */ b->hdr->content = NULL; - mutt_free_header(&b->hdr); + mutt_free_header (&b->hdr); } if (b->parts) mutt_free_body (&b->parts); - FREE (&b); + p_delete(&b); } *p = 0; } -void mutt_free_parameter (PARAMETER **p) +void mutt_free_parameter (PARAMETER ** p) { PARAMETER *t = *p; PARAMETER *o; - while (t) - { - FREE (&t->attribute); - FREE (&t->value); + while (t) { + p_delete(&t->attribute); + p_delete(&t->value); o = t; t = t->next; - FREE (&o); + p_delete(&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 *mutt_dup_header (HEADER * h) { HEADER *hnew; - hnew = mutt_new_header(); - memcpy(hnew, h, sizeof (HEADER)); + hnew = mutt_new_header (); + memcpy (hnew, h, sizeof (HEADER)); return hnew; } -void mutt_free_header (HEADER **h) +void mutt_free_header (HEADER ** h) { - if(!h || !*h) return; + if (!h || !*h) + return; mutt_free_envelope (&(*h)->env); mutt_free_body (&(*h)->content); - FREE (&(*h)->maildir_flags); - FREE (&(*h)->tree); - FREE (&(*h)->path); + p_delete(&(*h)->maildir_flags); + p_delete(&(*h)->tree); + p_delete(&(*h)->path); #ifdef MIXMASTER mutt_free_list (&(*h)->chain); #endif #if defined USE_POP || defined USE_IMAP || defined USE_NNTP - FREE (&(*h)->data); + p_delete(&(*h)->data); #endif - FREE (h); + p_delete(h); } /* returns true if the header contained in "s" is in list "t" */ -int mutt_matches_ignore (const char *s, 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)) || *t->data == '*') + for (; t; t = t->next) { + if (!ascii_strncasecmp (s, t->data, m_strlen(t->data)) + || *t->data == '*') return 1; } return 0; } -/* prepend the path part of *path to *link */ -void mutt_expand_link (char *newpath, const char *path, const char *link) +/* prepend the path part of *path to *lnk */ +void mutt_expand_link (char *newpath, const char *path, const char *lnk) { const char *lb = NULL; size_t len; - /* link is full path */ - if (*link == '/') - { - strfcpy (newpath, link, _POSIX_PATH_MAX); + /* lnk is full path */ + if (*lnk == '/') { + m_strcpy(newpath, _POSIX_PATH_MAX, lnk); return; } - if ((lb = strrchr (path, '/')) == NULL) - { - /* no path in link */ - strfcpy (newpath, link, _POSIX_PATH_MAX); + if ((lb = strrchr (path, '/')) == NULL) { + /* no path in lnk */ + m_strcpy(newpath, _POSIX_PATH_MAX, lnk); return; } len = lb - path + 1; memcpy (newpath, path, len); - strfcpy (newpath + len, link, _POSIX_PATH_MAX - len); + m_strcpy(newpath + len, _POSIX_PATH_MAX - len, lnk); } char *mutt_expand_path (char *s, size_t slen) @@ -333,155 +295,144 @@ char *_mutt_expand_path (char *s, size_t slen, int rx) char tmp[_POSIX_PATH_MAX]; char *t; - char *tail = ""; + const char *tail = ""; int recurse = 0; - - do - { + + do { recurse = 0; - switch (*s) - { - case '~': + switch (*s) { + case '~': { - if (*(s + 1) == '/' || *(s + 1) == 0) - { - strfcpy (p, NONULL(Homedir), sizeof (p)); - tail = s + 1; - } - else - { - struct passwd *pw; - if ((t = strchr (s + 1, '/'))) - *t = 0; - - if ((pw = getpwnam (s + 1))) - { - strfcpy (p, pw->pw_dir, sizeof (p)); - if (t) - { - *t = '/'; - tail = t; - } - else - tail = ""; - } - else - { - /* user not found! */ - if (t) - *t = '/'; - *p = '\0'; - tail = s; - } - } + if (*(s + 1) == '/' || *(s + 1) == 0) { + m_strcpy(p, sizeof(p), NONULL(Homedir)); + tail = s + 1; + } + else { + struct passwd *pw; + + if ((t = strchr (s + 1, '/'))) + *t = 0; + + if ((pw = getpwnam (s + 1))) { + m_strcpy(p, sizeof(p), pw->pw_dir); + if (t) { + *t = '/'; + tail = t; + } + else + tail = ""; + } + else { + /* user not found! */ + if (t) + *t = '/'; + *p = '\0'; + tail = s; + } + } } break; - - case '=': - case '+': + + case '=': + 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] == '/')) - strfcpy (p, NONULL (Maildir), sizeof (p)); - else + /* if folder = imap[s]://host/: don't append slash */ + if (imap_is_magic (NONULL (Maildir), NULL) == M_IMAP && + Maildir[m_strlen(Maildir) - 1] == '/') + m_strcpy(p, sizeof(p), NONULL(Maildir)); + else #endif - snprintf (p, sizeof (p), "%s/", NONULL (Maildir)); - - tail = s + 1; + snprintf (p, sizeof (p), "%s/", NONULL (Maildir)); + + tail = s + 1; } break; - + /* elm compatibility, @ expands alias to user name */ - - case '@': + + case '@': { - HEADER *h; - ADDRESS *alias; - - if ((alias = mutt_lookup_alias (s + 1))) - { - h = mutt_new_header(); - h->env = mutt_new_envelope(); - h->env->from = h->env->to = alias; - mutt_default_save (p, sizeof (p), h); - h->env->from = h->env->to = NULL; - mutt_free_header (&h); - /* Avoid infinite recursion if the resulting folder starts with '@' */ - if (*p != '@') - recurse = 1; - - tail = ""; - } + HEADER *h; + ADDRESS *alias; + + if ((alias = mutt_lookup_alias (s + 1))) { + h = mutt_new_header (); + h->env = mutt_new_envelope (); + h->env->from = h->env->to = alias; + mutt_default_save (p, sizeof (p), h); + h->env->from = h->env->to = NULL; + mutt_free_header (&h); + /* Avoid infinite recursion if the resulting folder starts with '@' */ + if (*p != '@') + recurse = 1; + + tail = ""; + } } break; - - case '>': + + case '>': { - strfcpy (p, NONULL(Inbox), sizeof (p)); - tail = s + 1; + m_strcpy(p, sizeof(p), NONULL(Inbox)); + tail = s + 1; } break; - - case '<': + + case '<': { - strfcpy (p, NONULL(Outbox), sizeof (p)); - tail = s + 1; + m_strcpy(p, sizeof(p), NONULL(Outbox)); + tail = s + 1; } break; - - case '!': + + case '!': { - if (*(s+1) == '!') - { - strfcpy (p, NONULL(LastFolder), sizeof (p)); - tail = s + 2; - } - else - { - strfcpy (p, NONULL(Spoolfile), sizeof (p)); - tail = s + 1; - } + if (*(s + 1) == '!') { + m_strcpy(p, sizeof(p), NONULL(LastFolder)); + tail = s + 2; + } + else { + m_strcpy(p, sizeof(p), NONULL(Spoolfile)); + tail = s + 1; + } } break; - - case '-': + + case '-': { - strfcpy (p, NONULL(LastFolder), sizeof (p)); - tail = s + 1; + m_strcpy(p, sizeof(p), NONULL(LastFolder)); + tail = s + 1; } break; - - default: + + case '^': + { + m_strcpy(p, sizeof(p), NONULL(CurrentFolder)); + tail = s + 1; + } + break; + + default: { - *p = '\0'; - tail = s; + *p = '\0'; + tail = s; } } - if (rx && *p && !recurse) - { + if (rx && *p && !recurse) { mutt_rx_sanitize_string (q, sizeof (q), p); snprintf (tmp, sizeof (tmp), "%s%s", q, tail); } else snprintf (tmp, sizeof (tmp), "%s%s", p, tail); - - strfcpy (s, tmp, slen); + + m_strcpy(s, slen, tmp); } 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); } @@ -499,41 +450,38 @@ char *mutt_gecos_name (char *dest, size_t destlen, struct passwd *pw) size_t pwnl; int idx; char *p; - - if (!pw || !pw->pw_gecos) + + if (!pw || !pw->pw_gecos) return NULL; - memset (dest, 0, destlen); - - if (GecosMask.rx) - { + p_clear(dest, destlen); + + if (GecosMask.rx) { if (regexec (GecosMask.rx, pw->pw_gecos, 1, pat_match, 0) == 0) - strfcpy (dest, pw->pw_gecos + pat_match[0].rm_so, - MIN (pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen)); + m_strcpy(dest, MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen), + pw->pw_gecos + pat_match[0].rm_so); } else if ((p = strchr (pw->pw_gecos, ','))) - strfcpy (dest, pw->pw_gecos, MIN (destlen, p - pw->pw_gecos + 1)); + m_strcpy(dest, MIN(destlen, p - pw->pw_gecos + 1), pw->pw_gecos); else - strfcpy (dest, pw->pw_gecos, destlen); + m_strcpy(dest, destlen, pw->pw_gecos); - pwnl = strlen (pw->pw_name); + pwnl = m_strlen(pw->pw_name); - for (idx = 0; dest[idx]; idx++) - { - if (dest[idx] == '&') - { + for (idx = 0; dest[idx]; idx++) { + if (dest[idx] == '&') { memmove (&dest[idx + pwnl], &dest[idx + 1], - MAX(destlen - idx - pwnl - 1, 0)); - memcpy (&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl)); + MAX (destlen - idx - pwnl - 1, 0)); + memcpy (&dest[idx], pw->pw_name, MIN (destlen - idx - 1, pwnl)); dest[idx] = toupper ((unsigned char) dest[idx]); } } - + return dest; } - -char *mutt_get_parameter (const char *s, PARAMETER *p) + +char *mutt_get_parameter (const char *s, PARAMETER * p) { for (; p; p = p->next) if (ascii_strcasecmp (s, p->attribute) == 0) @@ -542,40 +490,36 @@ char *mutt_get_parameter (const char *s, PARAMETER *p) return NULL; } -void mutt_set_parameter (const char *attribute, const char *value, PARAMETER **p) +void mutt_set_parameter (const char *attribute, const char *value, + PARAMETER ** p) { PARAMETER *q; - if (!value) - { + if (!value) { mutt_delete_parameter (attribute, p); return; } - - for(q = *p; q; q = q->next) - { - if (ascii_strcasecmp (attribute, q->attribute) == 0) - { - mutt_str_replace (&q->value, value); + + for (q = *p; q; q = q->next) { + if (ascii_strcasecmp (attribute, q->attribute) == 0) { + str_replace (&q->value, value); return; } } - - q = mutt_new_parameter(); - q->attribute = safe_strdup(attribute); - q->value = safe_strdup(value); + + q = mutt_new_parameter (); + q->attribute = m_strdup(attribute); + q->value = m_strdup(value); q->next = *p; *p = q; } -void mutt_delete_parameter (const char *attribute, PARAMETER **p) +void mutt_delete_parameter (const char *attribute, PARAMETER ** p) { PARAMETER *q; - - for (q = *p; q; p = &q->next, q = q->next) - { - if (ascii_strcasecmp (attribute, q->attribute) == 0) - { + + for (q = *p; q; p = &q->next, q = q->next) { + if (ascii_strcasecmp (attribute, q->attribute) == 0) { *p = q->next; q->next = NULL; mutt_free_parameter (&q); @@ -585,52 +529,49 @@ void mutt_delete_parameter (const char *attribute, PARAMETER **p) } /* returns 1 if Mutt can't display this type of data, 0 otherwise */ -int mutt_needs_mailcap (BODY *m) +int mutt_needs_mailcap (BODY * m) { - switch (m->type) - { - case TYPETEXT: - - if (!ascii_strcasecmp ("plain", m->subtype) || - !ascii_strcasecmp ("rfc822-headers", m->subtype) || - !ascii_strcasecmp ("enriched", m->subtype)) - return 0; - break; + switch (m->type) { + case TYPETEXT: - case TYPEAPPLICATION: - if((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp(m)) - return 0; - if((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(m)) - return 0; - break; + if (!ascii_strcasecmp ("plain", m->subtype) || + !ascii_strcasecmp ("rfc822-headers", m->subtype) || + !ascii_strcasecmp ("enriched", m->subtype)) + return 0; + break; - case TYPEMULTIPART: - case TYPEMESSAGE: + case TYPEAPPLICATION: + if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (m)) + return 0; + if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime (m)) return 0; + break; + + case TYPEMULTIPART: + case TYPEMESSAGE: + return 0; } return 1; } -int mutt_is_text_part (BODY *b) +int mutt_is_text_part (BODY * b) { int t = b->type; char *s = b->subtype; - + if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)) return 0; if (t == TYPETEXT) return 1; - if (t == TYPEMESSAGE) - { + if (t == TYPEMESSAGE) { if (!ascii_strcasecmp ("delivery-status", s)) return 1; } - if ((WithCrypto & APPLICATION_PGP) && t == TYPEAPPLICATION) - { + if ((WithCrypto & APPLICATION_PGP) && t == TYPEAPPLICATION) { if (!ascii_strcasecmp ("pgp-keys", s)) return 1; } @@ -638,9 +579,10 @@ int mutt_is_text_part (BODY *b) return 0; } -void mutt_free_envelope (ENVELOPE **p) +void mutt_free_envelope (ENVELOPE ** p) { - if (!*p) return; + if (!*p) + return; rfc822_free_address (&(*p)->return_path); rfc822_free_address (&(*p)->from); rfc822_free_address (&(*p)->to); @@ -650,46 +592,92 @@ 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); + p_delete(&(*p)->list_post); + p_delete(&(*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); + p_delete(&(*p)->message_id); + p_delete(&(*p)->supersedes); + p_delete(&(*p)->date); + p_delete(&(*p)->x_label); + p_delete(&(*p)->organization); #ifdef USE_NNTP - FREE (&(*p)->newsgroups); - FREE (&(*p)->xref); - FREE (&(*p)->followup_to); - FREE (&(*p)->x_comment_to); + p_delete(&(*p)->newsgroups); + p_delete(&(*p)->xref); + p_delete(&(*p)->followup_to); + p_delete(&(*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); + p_delete(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); } -void mutt_free_alias (ALIAS **p) +void mutt_free_alias (ALIAS ** p) { ALIAS *t; - while (*p) - { + while (*p) { t = *p; *p = (*p)->next; - FREE (&t->name); + p_delete(&t->name); rfc822_free_address (&t->addr); - FREE (&t); + p_delete(&t); } } @@ -703,34 +691,29 @@ void mutt_pretty_mailbox (char *s) scheme = url_check_scheme (s); #ifdef USE_IMAP - if (scheme == U_IMAP || scheme == U_IMAPS) - { + if (scheme == U_IMAP || scheme == U_IMAPS) { imap_pretty_mailbox (s); return; } #endif /* if s is an url, only collapse path component */ - if (scheme != U_UNKNOWN) - { - p = strchr(s, ':')+1; + if (scheme != U_UNKNOWN) { + p = strchr (s, ':') + 1; if (!strncmp (p, "//", 2)) - q = strchr (p+2, '/'); + q = strchr (p + 2, '/'); if (!q) q = strchr (p, '\0'); p = q; } - + /* first attempt to collapse the pathname */ - while (*p) - { - if (*p == '/' && p[1] == '/') - { + while (*p) { + if (*p == '/' && p[1] == '/') { *q++ = '/'; p += 2; } - else if (p[0] == '/' && p[1] == '.' && p[2] == '/') - { + else if (p[0] == '/' && p[1] == '.' && p[2] == '/') { *q++ = '/'; p += 3; } @@ -739,187 +722,179 @@ void mutt_pretty_mailbox (char *s) } *q = 0; - if (mutt_strncmp (s, Maildir, (len = mutt_strlen (Maildir))) == 0 && - s[len] == '/') - { + if (m_strncmp(s, Maildir, (len = m_strlen(Maildir))) == 0 && + s[len] == '/') { *s++ = '='; - memmove (s, s + len, mutt_strlen (s + len) + 1); + memmove (s, s + len, m_strlen(s + len) + 1); } - else if (mutt_strncmp (s, Homedir, (len = mutt_strlen (Homedir))) == 0 && - s[len] == '/') - { + else if (m_strncmp(s, Homedir, (len = m_strlen(Homedir))) == 0 && + s[len] == '/') { *s++ = '~'; - memmove (s, s + len - 1, mutt_strlen (s + len - 1) + 1); + memmove (s, s + len - 1, m_strlen(s + len - 1) + 1); } } void mutt_pretty_size (char *s, size_t len, long n) { if (n == 0) - strfcpy (s, "0K", len); - else if (n < 10189) /* 0.1K - 9.9K */ + m_strcpy(s, len, "0K"); + else if (n < 10189) /* 0.1K - 9.9K */ snprintf (s, len, "%3.1fK", (n < 103) ? 0.1 : n / 1024.0); - else if (n < 1023949) /* 10K - 999K */ - { + else if (n < 1023949) { /* 10K - 999K */ /* 51 is magic which causes 10189/10240 to be rounded up to 10 */ snprintf (s, len, "%ldK", (n + 51) / 1024); } - else if (n < 10433332) /* 1.0M - 9.9M */ + else if (n < 10433332) /* 1.0M - 9.9M */ snprintf (s, len, "%3.1fM", n / 1048576.0); - else /* 10M+ */ - { + else { /* 10M+ */ + /* (10433332 + 52428) / 1048576 = 10 */ snprintf (s, len, "%ldM", (n + 52428) / 1048576); } } -void mutt_expand_file_fmt (char *dest, size_t destlen, const char *fmt, const char *src) +void mutt_expand_file_fmt (char *dest, size_t destlen, const char *fmt, + const char *src) { char tmp[LONG_STRING]; - + mutt_quote_filename (tmp, sizeof (tmp), src); mutt_expand_fmt (dest, destlen, fmt, tmp); } -void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, const char *src) +void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, + const char *src) { const char *p; char *d; size_t slen; int found = 0; - slen = mutt_strlen (src); + slen = m_strlen(src); destlen--; - - for (p = fmt, d = dest; destlen && *p; p++) - { - if (*p == '%') - { - switch (p[1]) - { - case '%': - *d++ = *p++; - destlen--; - break; - case 's': - found = 1; - strfcpy (d, src, destlen + 1); - d += destlen > slen ? slen : destlen; - destlen -= destlen > slen ? slen : destlen; - p++; - break; - default: - *d++ = *p; - destlen--; - break; + + for (p = fmt, d = dest; destlen && *p; p++) { + if (*p == '%') { + switch (p[1]) { + case '%': + *d++ = *p++; + destlen--; + break; + case 's': + found = 1; + m_strcpy(d, destlen + 1, src); + d += destlen > slen ? slen : destlen; + destlen -= destlen > slen ? slen : destlen; + p++; + break; + default: + *d++ = *p; + destlen--; + break; } } - else - { + else { *d++ = *p; destlen--; } } - + *d = '\0'; - - if (!found && destlen > 0) - { - safe_strcat (dest, destlen, " "); - safe_strcat (dest, destlen, src); + + if (!found && destlen > 0) { + m_strcat(dest, destlen, " "); + m_strcat(dest, destlen, src); } - + } /* return 0 on success, -1 on abort, 1 on error */ int mutt_check_overwrite (const char *attname, const char *path, - char *fname, size_t flen, int *append, char **directory) + char *fname, size_t flen, int *append, + char **directory) { int rc = 0; char tmp[_POSIX_PATH_MAX]; struct stat st; - strfcpy (fname, path, flen); + m_strcpy(fname, flen, path); if (access (fname, F_OK) != 0) return 0; if (stat (fname, &st) != 0) return -1; - if (S_ISDIR (st.st_mode)) - { - if (directory) - { + if (S_ISDIR (st.st_mode)) { + if (directory) { switch (mutt_multi_choice - (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), _("yna"))) - { - case 3: /* all */ - mutt_str_replace (directory, fname); - break; - case 1: /* yes */ - FREE (directory); - break; - case -1: /* abort */ - FREE (directory); - return -1; - case 2: /* no */ - FREE (directory); - return 1; + (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), + _("yna"))) { + case 3: /* all */ + str_replace (directory, fname); + break; + case 1: /* yes */ + p_delete(directory); + break; + case -1: /* abort */ + p_delete(directory); + return -1; + case 2: /* no */ + p_delete(directory); + return 1; } } - else if ((rc = mutt_yesorno (_("File is a directory, save under it?"), M_YES)) != M_YES) + else + if ((rc = + mutt_yesorno (_("File is a directory, save under it?"), + M_YES)) != M_YES) return (rc == M_NO) ? 1 : -1; - if (!attname || !attname[0]) - { + if (!attname || !attname[0]) { tmp[0] = 0; if (mutt_get_field (_("File under directory: "), tmp, sizeof (tmp), - M_FILE | M_CLEAR) != 0 || !tmp[0]) - return (-1); - mutt_concat_path (fname, path, tmp, flen); + M_FILE | M_CLEAR) != 0 || !tmp[0]) + return (-1); + mutt_concat_path(fname, flen, path, tmp); } else - mutt_concat_path (fname, path, mutt_basename (attname), flen); + mutt_concat_path(fname, flen, path, mutt_basename(attname)); } - - if (*append == 0 && access (fname, F_OK) == 0) - { + + if (*append == 0 && access (fname, F_OK) == 0) { switch (mutt_multi_choice - (_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"), _("oac"))) + (_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"), _("oac"))) { - case -1: /* abort */ - return -1; - case 3: /* cancel */ - return 1; + case -1: /* abort */ + return -1; + case 3: /* cancel */ + return 1; - case 2: /* append */ - *append = M_SAVE_APPEND; - break; - case 1: /* overwrite */ - *append = M_SAVE_OVERWRITE; - break; + case 2: /* append */ + *append = M_SAVE_APPEND; + break; + case 1: /* overwrite */ + *append = M_SAVE_OVERWRITE; + break; } } return 0; } -void mutt_save_path (char *d, size_t dsize, ADDRESS *a) +void mutt_save_path (char *d, size_t dsize, ADDRESS * a) { - if (a && a->mailbox) - { - strfcpy (d, a->mailbox, dsize); - if (!option (OPTSAVEADDRESS)) - { + if (a && a->mailbox) { + m_strcpy(d, dsize, a->mailbox); + if (!option (OPTSAVEADDRESS)) { char *p; if ((p = strpbrk (d, "%@"))) - *p = 0; + *p = 0; } - mutt_strlower (d); + str_tolower (d); } else *d = 0; } -void mutt_safe_path (char *s, size_t l, ADDRESS *a) +void mutt_safe_path (char *s, size_t l, ADDRESS * a) { char *p; @@ -931,11 +906,14 @@ void mutt_safe_path (char *s, size_t l, ADDRESS *a) /* counts how many characters in s can be skipped while none of the * characters of c appears */ -int mutt_skipchars (const char* s, const char* c) { +int mutt_skipchars (const char *s, const char *c) +{ int ret = 0; - const char* p = s; + const char *p = s; + while (s && *s) { - register const char* t = c; + register const char *t = c; + while (t && *t) { if (*t == *s) return (ret); @@ -944,237 +922,220 @@ int mutt_skipchars (const char* s, const char* c) { ret++; s++; } - return (mutt_strlen (p)); + return (m_strlen(p)); } -void mutt_FormatString (char *dest, /* output buffer */ - size_t destlen, /* output buffer len */ - const char *src, /* template string */ - format_t *callback, /* callback for processing */ - unsigned long data, /* callback data */ - format_flag flags) /* callback flags */ -{ +void mutt_FormatString (char *dest, /* output buffer */ + size_t destlen, /* output buffer len */ + const char *src, /* template string */ + format_t * callback, /* callback for processing */ + unsigned long data, /* callback data */ + format_flag flags) +{ /* callback flags */ char prefix[SHORT_STRING], buf[LONG_STRING], *cp, *wptr = dest, ch; char ifstring[SHORT_STRING], elsestring[SHORT_STRING]; size_t wlen, count, len, col, wid; prefix[0] = '\0'; - destlen--; /* save room for the terminal \0 */ + destlen--; /* save room for the terminal \0 */ wlen = (flags & M_FORMAT_ARROWCURSOR && option (OPTARROWCURSOR)) ? 3 : 0; col = wlen; - - while (*src && wlen < destlen) - { - if (*src == '%') - { - if (*++src == '%') - { - *wptr++ = '%'; - wlen++; - col++; - src++; - continue; + + while (*src && wlen < destlen) { + if (*src == '%') { + if (*++src == '%') { + *wptr++ = '%'; + wlen++; + col++; + src++; + continue; } - if (*src == '?') - { - flags |= M_FORMAT_OPTIONAL; - src++; + if (*src == '?') { + flags |= M_FORMAT_OPTIONAL; + src++; } - else - { - flags &= ~M_FORMAT_OPTIONAL; - - /* eat the format string */ - cp = prefix; - count = 0; - while (count < sizeof (prefix) && - (isdigit ((unsigned char) *src) || *src == '.' || *src == '-')) - { - *cp++ = *src++; - count++; - } - *cp = 0; + else { + flags &= ~M_FORMAT_OPTIONAL; + + /* eat the format string */ + cp = prefix; + count = 0; + while (count < sizeof (prefix) && + (isdigit ((unsigned char) *src) || *src == '.' || *src == '-')) + { + *cp++ = *src++; + count++; + } + *cp = 0; } if (!*src) - break; /* bad format */ + break; /* bad format */ - ch = *src++; /* save the character to switch on */ + ch = *src++; /* save the character to switch on */ - if (flags & M_FORMAT_OPTIONAL) - { + if (flags & M_FORMAT_OPTIONAL) { if (*src != '?') - break; /* bad format */ + break; /* bad format */ src++; /* eat the `if' part of the string */ cp = ifstring; - count = 0; - while (count < sizeof (ifstring) && *src && *src != '?' && *src != '&') - { + count = 0; + while (count < sizeof (ifstring) && *src && *src != '?' + && *src != '&') { + *cp++ = *src++; + count++; + } + *cp = 0; + + /* eat the `else' part of the string (optional) */ + if (*src == '&') + src++; /* skip the & */ + cp = elsestring; + count = 0; + while (count < sizeof (elsestring) && *src && *src != '?') { *cp++ = *src++; - count++; - } + count++; + } *cp = 0; - /* eat the `else' part of the string (optional) */ - if (*src == '&') - src++; /* skip the & */ - cp = elsestring; - count = 0; - while (count < sizeof (elsestring) && *src && *src != '?') - { - *cp++ = *src++; - count++; - } - *cp = 0; - - if (!*src) - break; /* bad format */ - - src++; /* move past the trailing `?' */ + if (!*src) + break; /* bad format */ + + src++; /* move past the trailing `?' */ } /* handle generic cases first */ - if (ch == '>') - { - /* right justify to EOL */ - ch = *src++; /* pad char */ - /* calculate space left on line. if we've already written more data - than will fit on the line, ignore the rest of the line */ - if ( DrawFullLine || option(OPTSTATUSONTOP)) - count = (COLS < destlen ? COLS : destlen); - else - count = ((COLS-SidebarWidth) < destlen ? (COLS - SidebarWidth) : destlen); - 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); - if (count > wid) - { - count -= wid; /* how many chars to pad */ - memset (wptr, ch, count); - wptr += count; - col += count; - } - if (wid + wlen > destlen) - len = destlen - wlen; - else - len = wid; - memcpy (wptr, buf, len); - wptr += len; - wlen += len; - col += mutt_strwidth (buf); - } - break; /* skip rest of input */ + if (ch == '>') { + /* right justify to EOL */ + ch = *src++; /* pad char */ + /* calculate space left on line. if we've already written more data + than will fit on the line, ignore the rest of the line */ + if (DrawFullLine || option (OPTSTATUSONTOP)) + count = (COLS < destlen ? COLS : destlen); + else + count = ((COLS - SW) < destlen ? (COLS - SW) : destlen); + if (count > col) { + count -= col; /* how many columns left on this line */ + mutt_FormatString (buf, sizeof (buf), src, callback, data, flags); + wid = m_strlen(buf); + if (count > wid) { + count -= wid; /* how many chars to pad */ + memset (wptr, ch, count); + wptr += count; + col += count; + } + if (wid + wlen > destlen) + len = destlen - wlen; + else + len = wid; + memcpy (wptr, buf, len); + wptr += len; + wlen += len; + col += mutt_strwidth (buf); + } + break; /* skip rest of input */ } - else if (ch == '|') - { - /* pad to EOL */ - ch = *src++; - if (destlen > COLS) - destlen = COLS; - if (destlen > wlen) - { - count = destlen - wlen; - memset (wptr, ch, count); - wptr += count; - } - break; /* skip rest of input */ + else if (ch == '|') { + /* pad to EOL */ + ch = *src++; + if (destlen > COLS) + destlen = COLS; + if (destlen > wlen) { + count = destlen - wlen; + memset (wptr, ch, count); + wptr += count; + } + break; /* skip rest of input */ } - else - { - short tolower = 0; - short nodots = 0; - - while (ch == '_' || ch == ':') - { - if (ch == '_') - tolower = 1; - else if (ch == ':') - nodots = 1; - - ch = *src++; - } - - /* use callback function to handle this case */ - src = callback (buf, sizeof (buf), ch, src, prefix, ifstring, elsestring, data, flags); - - if (tolower) - mutt_strlower (buf); - if (nodots) - { - char *p = buf; - for (; *p; p++) - if (*p == '.') - *p = '_'; - } - - if ((len = mutt_strlen (buf)) + wlen > destlen) - len = (destlen - wlen > 0) ? (destlen - wlen) : 0; - - memcpy (wptr, buf, len); - wptr += len; - wlen += len; - col += mutt_strwidth (buf); + else { + short lower = 0; + short nodots = 0; + + while (ch == '_' || ch == ':') { + if (ch == '_') + lower = 1; + else if (ch == ':') + nodots = 1; + + ch = *src++; + } + + /* use callback function to handle this case */ + src = + callback (buf, sizeof (buf), ch, src, prefix, ifstring, elsestring, + data, flags); + + if (lower) + str_tolower (buf); + if (nodots) { + char *p = buf; + + for (; *p; p++) + if (*p == '.') + *p = '_'; + } + + if ((len = m_strlen(buf)) + wlen > destlen) + len = (destlen - wlen > 0) ? (destlen - wlen) : 0; + + memcpy (wptr, buf, len); + wptr += len; + wlen += len; + col += mutt_strwidth (buf); } } - else if (*src == '\\') - { + else if (*src == '\\') { if (!*++src) - break; - switch (*src) - { - case 'n': - *wptr = '\n'; - break; - case 't': - *wptr = '\t'; - break; - case 'r': - *wptr = '\r'; - break; - case 'f': - *wptr = '\f'; - break; - case 'v': - *wptr = '\v'; - break; - default: - *wptr = *src; - break; + break; + switch (*src) { + case 'n': + *wptr = '\n'; + break; + case 't': + *wptr = '\t'; + break; + case 'r': + *wptr = '\r'; + break; + case 'f': + *wptr = '\f'; + break; + case 'v': + *wptr = '\v'; + break; + default: + *wptr = *src; + break; } src++; wptr++; wlen++; col++; } - else - { + else { unsigned int bar = mutt_skipchars (src, "%\\"); - char* bar2 = safe_malloc (bar+1); - strfcpy (bar2, src, bar+1); + char *bar2 = p_dupstr(src, bar); + while (bar--) { *wptr++ = *src++; wlen++; } col += mutt_strwidth (bar2); - FREE(&bar2); + p_delete(&bar2); } } *wptr = 0; #if 0 - if (flags & M_FORMAT_MAKEPRINT) - { + if (flags & M_FORMAT_MAKEPRINT) { /* Make sure that the string is printable by changing all non-printable chars to dots, or spaces for non-printable whitespace */ - for (cp = dest ; *cp ; cp++) - if (!IsPrint (*cp) && - !((flags & M_FORMAT_TREE) && (*cp <= M_TREE_MAX))) - *cp = isspace ((unsigned char) *cp) ? ' ' : '.'; + for (cp = dest; *cp; cp++) + if (!IsPrint (*cp) && !((flags & M_FORMAT_TREE) && (*cp <= M_TREE_MAX))) + *cp = isspace ((unsigned char) *cp) ? ' ' : '.'; } #endif } @@ -1182,37 +1143,28 @@ void mutt_FormatString (char *dest, /* output buffer */ /* This function allows the user to specify a command to read stdout from in place of a normal file. If the last character in the string is a pipe (|), then we assume it is a commmand to run instead of a normal file. */ -FILE *mutt_open_read (const char *path, pid_t *thepid) +FILE *mutt_open_read (const char *path, pid_t * thepid) { - FILE *f; - struct stat s; - - int len = mutt_strlen (path); - - if (path[len - 1] == '|') - { - /* read from a pipe */ - - char *s = safe_strdup (path); - - s[len - 1] = 0; - mutt_endwin (NULL); - *thepid = mutt_create_filter (s, NULL, &f, NULL); - FREE (&s); - } - else - { - if (stat (path, &s) < 0) - return (NULL); - if (S_ISDIR (s.st_mode)) - { - errno = EINVAL; - return (NULL); + int len = m_strlen(path); + FILE *f; + + if (path[len - 1] == '|') { + char *s = m_strdup(path); + + /* read from a pipe */ + + s[len - 1] = 0; + mutt_endwin (NULL); + *thepid = mutt_create_filter (s, NULL, &f, NULL); + p_delete(&s); + } else { + f = fopen (path, "r"); + if (!f) + return NULL; + *thepid = -1; } - f = fopen (path, "r"); - *thepid = -1; - } - return (f); + + return (f); } /* returns 0 if OK to proceed, -1 to abort, 1 to retry */ @@ -1226,42 +1178,40 @@ int mutt_save_confirm (const char *s, struct stat *st) magic = mx_get_magic (s); #ifdef USE_POP - if (magic == M_POP) - { + if (magic == M_POP) { mutt_error _("Can't save message to POP mailbox."); + return 1; } #endif #ifdef USE_NNTP - if (magic == M_NNTP) - { + if (magic == M_NNTP) { mutt_error _("Can't save message to newsserver."); + return 0; } #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 || (m_strcmp(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; + ret = 1; else if (rc == -1) - ret = -1; + ret = -1; } } - else - { + + 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) #endif /* execute the block unconditionally if we don't use imap */ @@ -1269,112 +1219,34 @@ int mutt_save_confirm (const char *s, struct stat *st) st->st_mtime = 0; st->st_atime = 0; - if (errno == ENOENT) - { - if (option (OPTCONFIRMCREATE)) - { - snprintf (tmp, sizeof (tmp), _("Create %s?"), s); - if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) - ret = 1; - else if (rc == -1) - ret = -1; - } + if (errno == ENOENT) { + if (option (OPTCONFIRMCREATE)) { + snprintf (tmp, sizeof (tmp), _("Create %s?"), s); + if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) + ret = 1; + else if (rc == -1) + ret = -1; + } } - else - { - mutt_perror (s); - return 1; + else { + mutt_perror (s); + return 1; } } } - CLEARLINE (LINES-1); + CLEARLINE (LINES - 1); 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[0] == '\n') - strcpy (buf, Quotebuf); - 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++) - { + for (; *s; s++) { if (!IsPrint (*s)) *s = '?'; } } - + void mutt_sleep (short s) { if (SleepTime > s) @@ -1383,233 +1255,221 @@ 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) { struct utimbuf utim; struct stat _st; time_t mtime; - - if (!st) - { + + if (!st) { if (stat (f, &_st) == -1) return -1; st = &_st; } - if ((mtime = st->st_mtime) == time (NULL)) - { + if ((mtime = st->st_mtime) == time (NULL)) { mtime -= 1; utim.actime = mtime; utim.modtime = mtime; utime (f, &utim); } - - return mtime; -} -const char *mutt_make_version (void) -{ - static char vstring[STRING]; - snprintf (vstring, sizeof (vstring), "Mutt-ng %s (%s)", - MUTT_VERSION, ReleaseDate); - return vstring; + return mtime; } -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); +/* sets mtime of 'to' to mtime of 'from' */ +void mutt_set_mtime (const char* from, const char* to) { + struct utimbuf utim; + struct stat st; - return pp; + if (stat (from, &st) != -1) { + utim.actime = st.st_mtime; + utim.modtime = st.st_mtime; + utime (to, &utim); + } } -void mutt_free_regexp (REGEXP **pp) +const char *mutt_make_version (int full) { - FREE (&(*pp)->pattern); - regfree ((*pp)->rx); - FREE (&(*pp)->rx); - FREE (pp); -} + static char vstring[STRING]; -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); - } + if (full) + snprintf (vstring, sizeof (vstring), + "Mutt-ng %s-r%s (based on Mutt 1.5.11)", + MUTT_VERSION, MUTT_REVISION); + else + snprintf (vstring, sizeof (vstring), "mutt-ng/%s-r%s", + MUTT_VERSION, MUTT_REVISION); + return vstring; } -void mutt_free_spam_list (SPAM_LIST **list) +void mutt_free_spam_list (SPAM_LIST ** list) { SPAM_LIST *p; - - if (!list) return; - while (*list) - { + + if (!list) + return; + 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); + p_delete(&p->template); + p_delete(&p); } - - return 0; } -int mutt_match_spam_list (const char *s, SPAM_LIST *l, char *text, int x) +int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x) { static regmatch_t *pmatch = NULL; static int nmatch = 0; int i, n, tlen; char *p; - if (!s) return 0; + if (!s) + return 0; tlen = 0; - for (; l; l = l->next) - { + 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)); + if (l->nmatch > nmatch) { + p_realloc(&pmatch, l->nmatch); nmatch = l->nmatch; } /* Does this pattern match? */ - 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)); + if (regexec + (l->rx->rx, s, (size_t) l->nmatch, (regmatch_t *) pmatch, + (int) 0) == 0) { + 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;) - { - if (*p == '%') - { - n = atoi(++p); /* find pmatch index */ - while (isdigit(*p)) - ++p; /* skip subst token */ - for (i = pmatch[n].rm_so; (i < pmatch[n].rm_eo) && (tlen < x); i++) - text[tlen++] = s[i]; - } - else - { - text[tlen++] = *p++; - } + for (p = l->template; *p;) { + if (*p == '%') { + n = atoi (++p); /* find pmatch index */ + while (isdigit ((unsigned char) *p)) + ++p; /* skip subst token */ + for (i = pmatch[n].rm_so; (i < pmatch[n].rm_eo) && (tlen < x); i++) + text[tlen++] = s[i]; + } + else { + text[tlen++] = *p++; + } } 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 (m_strcmp(a->mailbox, b->mailbox) || + m_strcmp(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 (m_strcmp(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 (m_strcmp(e1->message_id, e2->message_id) || + m_strcmp(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 (m_strcmp(p1->attribute, p2->attribute) || + m_strcmp(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 || + m_strcmp(b1->subtype, b2->subtype) || + m_strcmp(b1->description, b2->description) || + !mutt_cmp_param (b1->parameter, b2->parameter) || + b1->length != b2->length) + return (0); + return (1); +}