X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=init.c;h=0728ffee6468d582525db911a850e49b8d8f4dc0;hp=cbc9645aa5b1e5c2133086116420991178df6148;hb=c7ceecd31e97891dd5cf48536d4bddf2c1d7d9dd;hpb=07232d8229d07417da518d8c68a80f5386905d8d diff --git a/init.c b/init.c index cbc9645..0728ffe 100644 --- a/init.c +++ b/init.c @@ -16,6 +16,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include "mutt.h" #include "mapping.h" #include "mutt_curses.h" @@ -27,7 +31,7 @@ #include "mutt_crypt.h" #include "mutt_idna.h" -#if defined(USE_SSL) || defined(USE_NSS) +#if defined(USE_SSL) || defined(USE_NSS) || defined(USE_GNUTLS) #include "mutt_ssl.h" #endif @@ -365,6 +369,112 @@ static int add_to_rx_list (RX_LIST **list, const char *s, int flags, BUFFER *err return 0; } +static int add_to_spam_list (SPAM_LIST **list, const char *pat, const char *templ, BUFFER *err) +{ + SPAM_LIST *t = NULL, *last = NULL; + REGEXP *rx; + int n; + const char *p; + + if (!pat || !*pat || !templ) + return 0; + + if (!(rx = mutt_compile_regexp (pat, REG_ICASE))) + { + snprintf (err->data, err->dsize, _("Bad regexp: %s"), pat); + return -1; + } + + /* check to make sure the item is not already on this list */ + for (last = *list; last; last = last->next) + { + if (ascii_strcasecmp (rx->pattern, last->rx->pattern) == 0) + { + /* Already on the list. Formerly we just skipped this case, but + * now we're supporting removals, which means we're supporting + * re-adds conceptually. So we probably want this to imply a + * removal, then do an add. We can achieve the removal by freeing + * the template, and leaving t pointed at the current item. + */ + t = last; + safe_free(&t->template); + break; + } + if (!last->next) + break; + } + + /* If t is set, it's pointing into an extant SPAM_LIST* that we want to + * update. Otherwise we want to make a new one to link at the list's end. + */ + if (!t) + { + t = mutt_new_spam_list(); + t->rx = rx; + if (last) + last->next = t; + else + *list = t; + } + + /* Now t is the SPAM_LIST* that we want to modify. It is prepared. */ + t->template = safe_strdup(templ); + + /* Find highest match number in template string */ + t->nmatch = 0; + for (p = templ; *p;) + { + if (*p == '%') + { + n = atoi(++p); + if (n > t->nmatch) + t->nmatch = n; + while (*p && isdigit((int)*p)) + ++p; + } + else + ++p; + } + t->nmatch++; /* match 0 is always the whole expr */ + + return 0; +} + +static int remove_from_spam_list (SPAM_LIST **list, const char *pat) +{ + SPAM_LIST *spam, *prev; + int nremoved = 0; + + /* Being first is a special case. */ + spam = *list; + if (spam->rx && !mutt_strcmp(spam->rx->pattern, pat)) + { + *list = spam->next; + mutt_free_regexp(&spam->rx); + safe_free(&spam->template); + safe_free(&spam); + return 1; + } + + prev = spam; + for (spam = prev->next; spam;) + { + if (!mutt_strcmp(spam->rx->pattern, pat)) + { + prev->next = spam->next; + mutt_free_regexp(&spam->rx); + safe_free(&spam->template); + safe_free(&spam); + spam = prev->next; + ++nremoved; + } + else + spam = spam->next; + } + + return nremoved; +} + static void remove_from_list (LIST **l, const char *str) { @@ -396,12 +506,16 @@ static void remove_from_list (LIST **l, const char *str) } } -static void remove_from_rx_list (RX_LIST **l, const char *str) +static int remove_from_rx_list (RX_LIST **l, const char *str) { RX_LIST *p, *last = NULL; + int rv = -1; if (mutt_strcmp ("*", str) == 0) + { mutt_free_rx_list (l); /* ``unCMD *'' means delete all current entries */ + rv = 0; + } else { p = *l; @@ -416,6 +530,7 @@ static void remove_from_rx_list (RX_LIST **l, const char *str) else (*l) = p->next; FREE (&p); + rv = 0; } else { @@ -424,6 +539,75 @@ static void remove_from_rx_list (RX_LIST **l, const char *str) } } } + return (rv); +} + +static int parse_ifdef (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) +{ + int i, j, res = 0; + BUFFER token; + + memset (&token, 0, sizeof (token)); + mutt_extract_token (tmp, s, 0); + + /* is the item defined as a variable or a function? */ + if (!(res = (mutt_option_index (tmp->data) != -1))) + for (i = 0; !res && i < MENU_MAX; i++) + { + struct binding_t *b = km_get_table (Menus[i].value); + + if (!b) + continue; + + for (j = 0; b[j].name; j++) + if (!ascii_strncasecmp (tmp->data, b[j].name, mutt_strlen (tmp->data)) + && (mutt_strlen (b[j].name) == mutt_strlen (tmp->data))) + { + res = 1; + break; + } + } + /* check for feature_* */ + if (!res) { + char* p = NULL; + i = 0; + j = mutt_strlen (tmp->data); + /* need at least input of 'feature_X' */ + if (j >= 7) { + p = tmp->data + 7; + j -= 7; + while (Features[i].name) { + if (mutt_strlen (Features[i].name) == j && + ascii_strncasecmp (Features[i].name, p, j)) { + res = 1; + break; + } + i++; + } + } + } + + if (!MoreArgs (s)) + { + if (data) + snprintf (err->data, err->dsize, _("ifdef: too few arguments")); + else + snprintf (err->data, err->dsize, _("ifndef: too few arguments")); + return (-1); + } + mutt_extract_token (tmp, s, M_TOKEN_SPACE); + + if ((data && res) || (!data && !res)) + { + if (mutt_parse_rc_line (tmp->data, &token, err) == -1) + { + mutt_error ("Error: %s", err->data); + FREE (&token.data); + return (-1); + } + FREE (&token.data); + } + return 0; } static int parse_unignore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) @@ -468,6 +652,7 @@ static int parse_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) return 0; } +#if 0 static int _parse_rx_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, int flags) { do @@ -503,6 +688,124 @@ static int parse_rx_unlist (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER * return 0; } +#endif + +static void _alternates_clean (void) +{ + int i; + if (Context && Context->msgcount) + { + for (i = 0; i < Context->msgcount; i++) + Context->hdrs[i]->recip_valid = 0; + } +} + +static int parse_alternates (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + _alternates_clean(); + do + { + mutt_extract_token (buf, s, 0); + remove_from_rx_list (&UnAlternates, buf->data); + + if (add_to_rx_list (&Alternates, buf->data, REG_ICASE, err) != 0) + return -1; + } + while (MoreArgs (s)); + + return 0; +} + +static int parse_unalternates (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + _alternates_clean(); + do + { + mutt_extract_token (buf, s, 0); + remove_from_rx_list (&Alternates, buf->data); + + if (mutt_strcmp (buf->data, "*") && + add_to_rx_list (&UnAlternates, buf->data, REG_ICASE, err) != 0) + return -1; + + } + while (MoreArgs (s)); + + return 0; +} + +static int parse_spam_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + BUFFER templ; + + memset(&templ, 0, sizeof(templ)); + + /* Insist on at least one parameter */ + if (!MoreArgs(s)) + { + if (data == M_SPAM) + strfcpy(err->data, _("spam: no matching pattern"), err->dsize); + else + strfcpy(err->data, _("nospam: no matching pattern"), err->dsize); + return -1; + } + + /* Extract the first token, a regexp */ + mutt_extract_token (buf, s, 0); + + /* data should be either M_SPAM or M_NOSPAM. M_SPAM is for spam commands. */ + if (data == M_SPAM) + { + /* If there's a second parameter, it's a template for the spam tag. */ + if (MoreArgs(s)) + { + mutt_extract_token (&templ, s, 0); + + /* Add to the spam list. */ + if (add_to_spam_list (&SpamList, buf->data, templ.data, err) != 0) { + FREE(&templ.data); + return -1; + } + FREE(&templ.data); + } + + /* If not, try to remove from the nospam list. */ + else + { + remove_from_rx_list(&NoSpamList, buf->data); + } + + return 0; + } + + /* M_NOSPAM is for nospam commands. */ + else if (data == M_NOSPAM) + { + /* nospam only ever has one parameter. */ + + /* "*" is a special case. */ + if (!mutt_strcmp(buf->data, "*")) + { + mutt_free_spam_list (&SpamList); + mutt_free_rx_list (&NoSpamList); + return 0; + } + + /* If it's on the spam list, just remove it. */ + if (remove_from_spam_list(&SpamList, buf->data) != 0) + return 0; + + /* Otherwise, add it to the nospam list. */ + if (add_to_rx_list (&NoSpamList, buf->data, REG_ICASE, err) != 0) + return -1; + + return 0; + } + + /* This should not happen. */ + strfcpy(err->data, "This is no good at all.", err->dsize); + return -1; +} static int parse_unlist (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { @@ -524,14 +827,32 @@ static int parse_unlist (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err return 0; } +static int parse_lists (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + do + { + mutt_extract_token (buf, s, 0); + remove_from_rx_list (&UnMailLists, buf->data); + + if (add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0) + return -1; + } + while (MoreArgs (s)); + + return 0; +} static int parse_unlists (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { do { mutt_extract_token (buf, s, 0); - remove_from_rx_list (&MailLists, buf->data); remove_from_rx_list (&SubscribedLists, buf->data); + remove_from_rx_list (&MailLists, buf->data); + + if (mutt_strcmp (buf->data, "*") && + add_to_rx_list (&UnMailLists, buf->data, REG_ICASE, err) != 0) + return -1; } while (MoreArgs (s)); @@ -543,6 +864,9 @@ static int parse_subscribe (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER * do { mutt_extract_token (buf, s, 0); + remove_from_rx_list (&UnMailLists, buf->data); + remove_from_rx_list (&UnSubscribedLists, buf->data); + if (add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0) return -1; if (add_to_rx_list (&SubscribedLists, buf->data, REG_ICASE, err) != 0) @@ -552,6 +876,22 @@ static int parse_subscribe (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER * return 0; } + +static int parse_unsubscribe (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + do + { + mutt_extract_token (buf, s, 0); + remove_from_rx_list (&SubscribedLists, buf->data); + + if (mutt_strcmp (buf->data, "*") && + add_to_rx_list (&UnSubscribedLists, buf->data, REG_ICASE, err) != 0) + return -1; + } + while (MoreArgs (s)); + + return 0; +} static int parse_unalias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { @@ -614,6 +954,9 @@ static int parse_alias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) mutt_extract_token (buf, s, 0); + dprint (2, (debugfile, "parse_alias: First token is '%s'.\n", + buf->data)); + /* check to see if an alias with this name already exists */ for (; tmp; tmp = tmp->next) { @@ -641,6 +984,8 @@ static int parse_alias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) } mutt_extract_token (buf, s, M_TOKEN_QUOTE | M_TOKEN_SPACE | M_TOKEN_SEMICOLON); + dprint (2, (debugfile, "parse_alias: Second token is '%s'.\n", + buf->data)); tmp->addr = mutt_parse_adrlist (tmp->addr, buf->data); if (last) last->next = tmp; @@ -652,6 +997,21 @@ static int parse_alias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) estr, tmp->name); return -1; } +#ifdef DEBUG + if (debuglevel >= 2) + { + ADDRESS *a; + for (a = tmp->addr; a; a = a->next) + { + if (!a->group) + dprint (2, (debugfile, "parse_alias: %s\n", + a->mailbox)); + else + dprint (2, (debugfile, "parse_alias: Group %s\n", + a->mailbox)); + } + } +#endif return 0; } @@ -864,10 +1224,7 @@ static void mutt_restore_default (struct option_t *p) char *s = (char *) p->init; pp->rx = safe_calloc (1, sizeof (regex_t)); - pp->pattern = safe_strdup ((char *) p->init); - if (mutt_strcmp (p->option, "alternates") == 0) - flags |= REG_ICASE; - else if (mutt_strcmp (p->option, "mask") != 0) + if (mutt_strcmp (p->option, "mask") != 0) flags |= mutt_which_case ((const char *) p->init); if (mutt_strcmp (p->option, "mask") == 0 && *s == '!') { @@ -1015,7 +1372,7 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) if (DTYPE (MuttVars[idx].type) == DT_ADDR) rfc822_free_address ((ADDRESS **) MuttVars[idx].data); else - FREE (MuttVars[idx].data); + FREE ((void *)MuttVars[idx].data); } else if (query || *s->dptr != '=') { @@ -1044,7 +1401,7 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) if (DTYPE (MuttVars[idx].type) == DT_ADDR) rfc822_free_address ((ADDRESS **) MuttVars[idx].data); else - FREE (MuttVars[idx].data); + FREE ((void *)MuttVars[idx].data); mutt_extract_token (tmp, s, 0); if (DTYPE (MuttVars[idx].type) == DT_PATH) @@ -1079,8 +1436,7 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) break; } - if (option(OPTATTACHMSG) && (!mutt_strcmp(MuttVars[idx].option, "alternates") - || !mutt_strcmp(MuttVars[idx].option, "reply_regexp"))) + if (option(OPTATTACHMSG) && !mutt_strcmp(MuttVars[idx].option, "reply_regexp")) { snprintf (err->data, err->dsize, "Operation not permitted when in attach-message mode."); r = -1; @@ -1096,11 +1452,8 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) { int not = 0; - /* $alternates is case-insensitive, - $mask is case-sensitive */ - if (mutt_strcmp (MuttVars[idx].option, "alternates") == 0) - flags |= REG_ICASE; - else if (mutt_strcmp (MuttVars[idx].option, "mask") != 0) + /* $mask is case-sensitive */ + if (mutt_strcmp (MuttVars[idx].option, "mask") != 0) flags |= mutt_which_case (tmp->data); p = tmp->data; @@ -1155,15 +1508,6 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) } #undef CUR_ENV } - - if(Context && Context->msgcount && - mutt_strcmp(MuttVars[idx].option, "alternates") == 0) - { - int i; - - for(i = 0; i < Context->msgcount; i++) - Context->hdrs[i]->recip_valid = 0; - } } } else if (DTYPE(MuttVars[idx].type) == DT_MAGIC) @@ -1363,24 +1707,16 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) static int source_rc (const char *rcfile, BUFFER *err) { FILE *f; - int line = 0, rc = 0; + int line = 0, rc = 0, conv = 0; BUFFER token; char *linebuf = NULL; + char *currentline = NULL; size_t buflen; pid_t pid; - struct stat s; - - if (stat (rcfile, &s) < 0) - { - snprintf (err->data, err->dsize, _("%s: stat: %s"), rcfile, strerror (errno)); - return (-1); - } - if (!S_ISREG (s.st_mode)) - { - snprintf (err->data, err->dsize, _("%s: not a regular file"), rcfile); - return (-1); - } + dprint (2, (debugfile, "Reading configuration file '%s'.\n", + rcfile)); + if ((f = mutt_open_read (rcfile, &pid)) == NULL) { snprintf (err->data, err->dsize, "%s: %s", rcfile, strerror (errno)); @@ -1390,15 +1726,32 @@ static int source_rc (const char *rcfile, BUFFER *err) memset (&token, 0, sizeof (token)); while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL) { - if (mutt_parse_rc_line (linebuf, &token, err) == -1) + conv=ConfigCharset && (*ConfigCharset) && Charset; + if (conv) + { + currentline=safe_strdup(linebuf); + if (!currentline) continue; + mutt_convert_string(¤tline, ConfigCharset, Charset, 0); + } + else + currentline=linebuf; + + if (mutt_parse_rc_line (currentline, &token, err) == -1) { mutt_error (_("Error in %s, line %d: %s"), rcfile, line, err->data); - if (--rc < -MAXERRS) + if (--rc < -MAXERRS) + { + if (conv) FREE(¤tline); break; + } } else + { if (rc < 0) rc = -1; + } + if (conv) + FREE(¤tline); } FREE (&token.data); FREE (&linebuf); @@ -1853,7 +2206,7 @@ static void start_debug (void) { t = time (0); setbuf (debugfile, NULL); /* don't buffer the debugging output! */ - fprintf (debugfile, "Mutt %s started at %s.\nDebugging at level %d.\n\n", + fprintf (debugfile, "Mutt-ng %s started at %s.\nDebugging at level %d.\n\n", MUTT_VERSION, asctime (localtime (&t)), debuglevel); } }