/**
* @file
* Alternate address handling
*
* @authors
* Copyright (C) 2021 Richard Russon <rich@flatcap.org>
*
* @copyright
* 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, see <http://www.gnu.org/licenses/>.
*/
/**
* @page neo_alternates Alternate address handling
*
* Alternate address handling
*/
#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alternates.h"
#include "parse/lib.h"
#include "commands.h"
#include "mview.h"
static struct RegexList Alternates = STAILQ_HEAD_INITIALIZER(Alternates); ///< List of regexes to match the user's alternate email addresses
static struct RegexList UnAlternates = STAILQ_HEAD_INITIALIZER(UnAlternates); ///< List of regexes to exclude false matches in Alternates
static struct Notify *AlternatesNotify = NULL; ///< Notifications: #NotifyAlternates
/**
* alternates_cleanup - Free the alternates lists
*/
void alternates_cleanup(void)
{
notify_free(&AlternatesNotify);
mutt_regexlist_free(&Alternates);
mutt_regexlist_free(&UnAlternates);
}
/**
* alternates_init - Set up the alternates lists
*/
void alternates_init(void)
{
if (AlternatesNotify)
return;
AlternatesNotify = notify_new();
notify_set_parent(AlternatesNotify, NeoMutt->notify);
}
/**
* mutt_alternates_reset - Clear the recipient valid flag of all emails
* @param mv Mailbox view
*/
void mutt_alternates_reset(struct MailboxView *mv)
{
if (!mv || !mv->mailbox)
return;
struct Mailbox *m = mv->mailbox;
for (int i = 0; i < m->msg_count; i++)
{
struct Email *e = m->emails[i];
if (!e)
break;
e->recip_valid = false;
}
}
/**
* parse_alternates - Parse the 'alternates' command - Implements Command::parse() - @ingroup command_parse
*/
enum CommandResult parse_alternates(struct Buffer *buf, struct Buffer *s,
intptr_t data, struct Buffer *err)
{
struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
do
{
parse_extract_token(buf, s, TOKEN_NO_FLAGS);
if (parse_grouplist(&gl, buf, s, err) == -1)
goto bail;
mutt_regexlist_remove(&UnAlternates, buf->data);
if (mutt_regexlist_add(&Alternates, buf->data, REG_ICASE, err) != 0)
goto bail;
if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
goto bail;
} while (MoreArgs(s));
mutt_grouplist_destroy(&gl);
mutt_debug(LL_NOTIFY, "NT_ALTERN_ADD: %s\n", buf->data);
notify_send(AlternatesNotify, NT_ALTERN, NT_ALTERN_ADD, NULL);
return MUTT_CMD_SUCCESS;
bail:
mutt_grouplist_destroy(&gl);
return MUTT_CMD_ERROR;
}
/**
* parse_unalternates - Parse the 'unalternates' command - Implements Command::parse() - @ingroup command_parse
*/
enum CommandResult parse_unalternates(struct Buffer *buf, struct Buffer *s,
intptr_t data, struct Buffer *err)
{
do
{
parse_extract_token(buf, s, TOKEN_NO_FLAGS);
mutt_regexlist_remove(&Alternates, buf->data);
if (!mutt_str_equal(buf->data, "*") &&
(mutt_regexlist_add(&UnAlternates, buf->data, REG_ICASE, err) != 0))
{
return MUTT_CMD_ERROR;
}
} while (MoreArgs(s));
mutt_debug(LL_NOTIFY, "NT_ALTERN_DELETE: %s\n", buf->data);
notify_send(AlternatesNotify, NT_ALTERN, NT_ALTERN_DELETE, NULL);
return MUTT_CMD_SUCCESS;
}
/**
* mutt_alternates_match - Compare an Address to the Un/Alternates lists
* @param addr Address to check
* @retval true Address matches
*/
bool mutt_alternates_match(const char *addr)
{
if (!addr)
return false;
if (mutt_regexlist_match(&Alternates, addr))
{
mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr);
if (mutt_regexlist_match(&UnAlternates, addr))
mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr);
else
return true;
}
return false;
}