X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=alias.c;h=68afc256a0c64e24632a477113dbef4a91f6a6be;hp=add80282f0eda7051c57e2013096a54d8de8ce0e;hb=6ebff74ad242d4c56fb7762965b19cee14fd2daa;hpb=723f7ae3f24f7881c9ce87abf933cd5bec4ac0bc diff --git a/alias.c b/alias.c index add8028..68afc25 100644 --- a/alias.c +++ b/alias.c @@ -1,3 +1,21 @@ +/* + * 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-2002 Michael R. Elkins @@ -7,21 +25,7 @@ * 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 -#include -#include -#include +#include #include @@ -29,10 +33,15 @@ #include #include -#include "mutt.h" +#include "alias.h" #include "mutt_idna.h" #include "sort.h" +char *AliasFmt; +char *AliasFile; +alias_t *Aliases; +rx_t GecosMask; + #define RSORT(x) (SortAlias & SORT_REVERSE) ? -x : x static struct mapping_t AliasHelp[] = { @@ -44,23 +53,94 @@ static struct mapping_t AliasHelp[] = { {NULL, OP_NULL} }; -void alias_wipe(alias_t *a) { - p_delete(&a->name); - address_delete(&a->addr); - alias_delete(&a->next); -} +static void mutt_alias_menu(char *, size_t, alias_t *); -address_t *alias_lookup(alias_t *list, const char *s) +const address_t *alias_lookup(const char *s) { - while (list) { + alias_t *list; + + for (list = Aliases; list; list = list->next) { if (!m_strcasecmp(s, list->name)) return list->addr; - list = list->next; } return NULL; } +/* This routine looks to see if the user has an alias defined for the given + address. */ +const address_t *alias_reverse_lookup(const address_t *a) +{ + alias_t *list; + + if (!a || !a->mailbox) + return NULL; + + for (list = Aliases; list; list = list->next) { + address_t *ap; + + /* cycle through all addresses if this is a group alias */ + for (ap = list->addr; ap; ap = ap->next) { + if (!ap->group && ap->mailbox + && !ascii_strcasecmp(ap->mailbox, a->mailbox)) + return ap; + } + } + + return NULL; +} + +static int string_is_address(const char *str, const char *u, const char *d) +{ + char buf[LONG_STRING]; + snprintf(buf, sizeof (buf), "%s@%s", NONULL(u), NONULL(d)); + return !ascii_strcasecmp(str, buf); +} + +/* returns TRUE if the given address belongs to the user. */ +int mutt_addr_is_user(address_t *addr) +{ + /* NULL address is assumed to be the user. */ + if (!addr) + return 1; + + if (!addr->mailbox) + return 0; + + if (!ascii_strcasecmp(addr->mailbox, Username) + || string_is_address(addr->mailbox, Username, Hostname) + || string_is_address(addr->mailbox, Username, mutt_fqdn(0)) + || string_is_address(addr->mailbox, Username, mutt_fqdn(1)) + || (From && !ascii_strcasecmp(From->mailbox, addr->mailbox))) + { + return 1; + } + + return rx_list_match(Alternates, addr->mailbox) + && !rx_list_match(UnAlternates, addr->mailbox); +} + +address_t *mutt_get_address(ENVELOPE *env, const char **pfxp) +{ +#define RETURN(s, adr) do { if (pfxp) *pfxp = s; return adr; } while (0) + + if (mutt_addr_is_user(env->from)) { + if (env->to && !mutt_is_mail_list(env->to)) { + RETURN("To", env->to); + } else { + RETURN("Cc", env->cc); + } + } else { + if (env->reply_to && !mutt_is_mail_list(env->reply_to)) { + RETURN("Reply-To", env->reply_to); + } else { + RETURN("From", env->from); + } + } + +#undef RETURN +} + /* Only characters which are non-special to both the RFC 822 and the mutt configuration parser are permitted. */ static int alias_sanitize(const char *s, char *d) @@ -141,7 +221,7 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) return; /* check to see if the user already has an alias defined */ - if (alias_lookup(Aliases, buf)) { + if (alias_lookup(buf)) { mutt_error _("You already have an alias defined with that name!"); return; } @@ -160,10 +240,10 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) mutt_addrlist_to_idna(adr, NULL); do { - const char *err = NULL; + char *err = NULL; if (mutt_get_field(_("Address: "), buf, sizeof(buf), 0) || !buf[0]) { - alias_delete(&new); + alias_list_wipe(&new); return; } @@ -173,6 +253,7 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) if (mutt_addrlist_to_idna(new->addr, &err)) { mutt_error(_("Error: '%s' is a bad IDN."), err); + p_delete(&err); mutt_sleep(1); continue; } @@ -185,7 +266,7 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) } if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), 0)) { - alias_delete(&new); + alias_list_wipe(&new); return; } new->addr->personal = m_strdup(buf); @@ -194,7 +275,7 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) rfc822_write_address(buf, sizeof(buf), new->addr, 1); snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), new->name, buf); if (mutt_yesorno(prompt, M_YES) != M_YES) { - alias_delete(&new); + alias_list_wipe(&new); return; } @@ -219,161 +300,91 @@ void mutt_create_alias(ENVELOPE *cur, address_t *iadr) buf[0] = '\0'; rfc822_write_address(buf, sizeof(buf), new->addr, 0); write_safe_address(rc, buf); - fclose(rc); + m_fclose(&rc); mutt_message _("Alias added."); } else { mutt_perror(buf); } } -/************* READ MARK *********************/ - - -static address_t *mutt_expand_aliases_r (address_t * a, LIST ** expn) +static address_t *mutt_expand_aliases_r(address_t *a, string_list_t **expn) { - address_t *head = NULL, *last = NULL, *t, *w; - LIST *u; - char i; - const char *fqdn; - - while (a) { - if (!a->group && !a->personal && a->mailbox - && strchr (a->mailbox, '@') == NULL) { - t = alias_lookup(Aliases, a->mailbox); - - if (t) { - i = 0; - for (u = *expn; u; u = u->next) { - if (m_strcmp(a->mailbox, u->data) == 0) { /* alias already found */ - debug_print(1, ("loop in alias found for '%s'\n", a->mailbox)); - i = 1; - break; - } + address_t *pop, *head = NULL; + address_t **last = &head; + + while ((pop = address_list_pop(&a))) { + if (!pop->group && !pop->personal + && pop->mailbox && !strchr(pop->mailbox, '@')) + { + const address_t *t = alias_lookup(pop->mailbox); + + if (t) { + string_list_t *u; + + for (u = *expn; u; u = u->next) { + if (!m_strcmp(pop->mailbox, u->data)) { /* alias already found */ + address_list_wipe(&pop); + continue; + } + } + + /* save the fact we saw it */ + u = string_item_new(); + u->data = m_strdup(pop->mailbox); + u->next = *expn; + *expn = u; + address_list_wipe(&pop); + + /* recurse */ + last = address_list_last(last); + *last = mutt_expand_aliases_r(address_list_dup(t), expn); + continue; + } else { + struct passwd *pw = getpwnam(pop->mailbox); + + if (pw) { + char namebuf[STRING]; + mutt_gecos_name(namebuf, sizeof(namebuf), pw, GecosMask.rx); + m_strreplace(&pop->personal, namebuf); + } + } } - if (!i) { - u = p_new(LIST, 1); - u->data = m_strdup(a->mailbox); - u->next = *expn; - *expn = u; - w = address_list_dup (t); - w = mutt_expand_aliases_r (w, expn); - if (head) - last->next = w; - else - head = last = w; - while (last && last->next) - last = last->next; - } - t = a; - a = a->next; - t->next = NULL; - address_delete (&t); - continue; - } - else { - struct passwd *pw = getpwnam (a->mailbox); - - if (pw) { - char namebuf[STRING]; - - mutt_gecos_name(namebuf, sizeof (namebuf), pw, GecosMask.rx); - m_strreplace(&a->personal, namebuf); - } - } + last = address_list_append(last, pop); } - if (head) { - last->next = a; - last = last->next; + if (option(OPTUSEDOMAIN)) { + /* now qualify all local addresses */ + const char *fqdn = mutt_fqdn(1); + if (fqdn) + rfc822_qualify(head, fqdn); } - else - head = last = a; - a = a->next; - last->next = NULL; - } - if (option (OPTUSEDOMAIN) && (fqdn = mutt_fqdn (1))) { - /* now qualify all local addresses */ - rfc822_qualify (head, fqdn); - } - - return (head); + return head; } -address_t *mutt_expand_aliases (address_t * a) +address_t *mutt_expand_aliases(address_t *a) { - address_t *t; - LIST *expn = NULL; /* previously expanded aliases to avoid loops */ + address_t *t; + string_list_t *expn = NULL; /* previously expanded aliases to avoid loops */ - t = mutt_expand_aliases_r (a, &expn); - mutt_free_list (&expn); - return (mutt_remove_duplicates (t)); + t = mutt_expand_aliases_r(a, &expn); + string_list_wipe(&expn); + address_list_uniq(t); + return t; } -void mutt_expand_aliases_env (ENVELOPE * env) +void mutt_expand_aliases_env(ENVELOPE *env) { - env->from = mutt_expand_aliases (env->from); - env->to = mutt_expand_aliases (env->to); - env->cc = mutt_expand_aliases (env->cc); - env->bcc = mutt_expand_aliases (env->bcc); - env->reply_to = mutt_expand_aliases (env->reply_to); - env->mail_followup_to = mutt_expand_aliases (env->mail_followup_to); + env->from = mutt_expand_aliases(env->from); + env->to = mutt_expand_aliases(env->to); + env->cc = mutt_expand_aliases(env->cc); + env->bcc = mutt_expand_aliases(env->bcc); + env->reply_to = mutt_expand_aliases(env->reply_to); + env->mail_followup_to = mutt_expand_aliases(env->mail_followup_to); } - -address_t *mutt_get_address (ENVELOPE * env, const char **pfxp) -{ - address_t *adr; - const char *pfx = NULL; - - if (mutt_addr_is_user (env->from)) { - if (env->to && !mutt_is_mail_list (env->to)) { - pfx = "To"; - adr = env->to; - } - else { - pfx = "Cc"; - adr = env->cc; - } - } - else if (env->reply_to && !mutt_is_mail_list (env->reply_to)) { - pfx = "Reply-To"; - adr = env->reply_to; - } - else { - adr = env->from; - pfx = "From"; - } - - if (pfxp) - *pfxp = pfx; - - return adr; -} - -/* - * This routine looks to see if the user has an alias defined for the given - * address. - */ -address_t *alias_reverse_lookup (address_t * a) -{ - alias_t *t = Aliases; - address_t *ap; - - if (!a || !a->mailbox) - return NULL; - - for (; t; t = t->next) { - /* cycle through all addresses if this is a group alias */ - for (ap = t->addr; ap; ap = ap->next) { - if (!ap->group && ap->mailbox && - ascii_strcasecmp (ap->mailbox, a->mailbox) == 0) - return ap; - } - } - return 0; -} +/************* READ MARK *********************/ /* alias_complete() -- alias completion routine * @@ -454,7 +465,7 @@ int mutt_alias_complete (char *s, size_t buflen) Aliases = a_cur->next; a_cur->next = NULL; - alias_delete(&a_cur); + alias_list_wipe(&a_cur); if (a_list) a_cur = a_list; @@ -470,64 +481,6 @@ int mutt_alias_complete (char *s, size_t buflen) return 0; } -static int string_is_address (const char *str, const char *u, const char *d) -{ - char buf[LONG_STRING]; - - snprintf (buf, sizeof (buf), "%s@%s", NONULL (u), NONULL (d)); - if (ascii_strcasecmp (str, buf) == 0) - return 1; - - return 0; -} - -/* returns TRUE if the given address belongs to the user. */ -int mutt_addr_is_user (address_t * addr) -{ - /* NULL address is assumed to be the user. */ - if (!addr) { - debug_print(5, ("yes, NULL address\n")); - return 1; - } - if (!addr->mailbox) { - debug_print(5, ("no, no mailbox\n")); - return 0; - } - - if (ascii_strcasecmp (addr->mailbox, Username) == 0) { - debug_print(5, ("yes, %s = %s\n", addr->mailbox, Username)); - return 1; - } - if (string_is_address (addr->mailbox, Username, Hostname)) { - debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, Hostname)); - return 1; - } - if (string_is_address (addr->mailbox, Username, mutt_fqdn (0))) { - debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (0))); - return 1; - } - if (string_is_address (addr->mailbox, Username, mutt_fqdn (1))) { - debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (1))); - return 1; - } - - if (From && !ascii_strcasecmp (From->mailbox, addr->mailbox)) { - debug_print(5, ("yes, %s = %s\n", addr->mailbox, From->mailbox)); - return 1; - } - - if (rx_list_match (Alternates, addr->mailbox)) { - debug_print(5, ("yes, %s matched by alternates.\n", addr->mailbox)); - if (rx_list_match (UnAlternates, addr->mailbox)) - debug_print(5, ("but, %s matched by unalternates.\n", addr->mailbox)); - else - return 1; - } - - debug_print(5, ("no, all failed.\n")); - return 0; -} - static const format_t *alias_format_str (char *dest, size_t destlen, char op, const format_t *src, const char *fmt, const char *ifstring __attribute__ ((unused)), @@ -718,5 +671,4 @@ new_aliases: mutt_menuDestroy (&menu); p_delete(&AliasTable); - }