Commit 5f7e56f4 authored by Rocco Rutte's avatar Rocco Rutte

Implement ungroup command. Closes #3304.

parent 28665507
/*
* Copyright (C) 2006 Thomas Roessler <[email protected]>
*
* Copyright (C) 2009 Rocco Rutte <[email protected]>
*
* 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.
*/
*/
#if HAVE_CONFIG_H
# include "config.h"
......@@ -37,10 +38,10 @@
group_t *mutt_pattern_group (const char *k)
{
group_t *p;
if (!k)
return 0;
if (!(p = hash_find (Groups, k)))
{
dprint (2, (debugfile, "mutt_pattern_group: Creating group %s.\n", k));
......@@ -48,10 +49,46 @@ group_t *mutt_pattern_group (const char *k)
p->name = safe_strdup (k);
hash_insert (Groups, p->name, p, 0);
}
return p;
}
static void group_free (void *p)
{
group_t *g = (group_t *)p;
if (!g)
return;
FREE(&g->name);
rfc822_free_address (&g->as);
mutt_free_rx_list (&g->rs);
FREE(&g);
}
int mutt_group_remove (group_t * g, BUFFER * err)
{
int h;
if (!g)
return -1;
h = Groups->hash_string ((const unsigned char *)g->name, Groups->nelem);
if (!hash_find_hash (Groups, h, g->name))
{
if (err)
snprintf (err->data, err->dsize, _("No such group: %s"), g->name);
return -1;
}
hash_delete_hash (Groups, h, g->name, g, group_free);
return 0;
}
static int empty_group (group_t *g)
{
if (!g)
return -1;
return !g->as && !g->rs;
}
void mutt_group_context_add (group_context_t **ctx, group_t *group)
{
for (; *ctx; ctx = &((*ctx)->next))
......@@ -59,7 +96,7 @@ void mutt_group_context_add (group_context_t **ctx, group_t *group)
if ((*ctx)->g == group)
return;
}
*ctx = safe_calloc (1, sizeof (group_context_t));
(*ctx)->g = group;
}
......@@ -82,40 +119,88 @@ void mutt_group_add_adrlist (group_t *g, ADDRESS *a)
return;
if (!a)
return;
for (p = &g->as; *p; p = &((*p)->next))
;
q = rfc822_cpy_adr (a, 0);
q = mutt_remove_xrefs (g->as, q);
*p = q;
}
static int mutt_group_remove_adrlist (group_t *g, ADDRESS *a)
{
ADDRESS *p;
if (!g)
return -1;
if (!a)
return -1;
for (p = a; p; p = p->next)
rfc822_remove_from_adrlist (&g->as, p->mailbox);
return 0;
}
static int mutt_group_add_rx (group_t *g, const char *s, int flags, BUFFER *err)
{
return mutt_add_to_rx_list (&g->rs, s, flags, err);
}
static int mutt_group_remove_rx (group_t *g, const char *s)
{
return mutt_remove_from_rx_list (&g->rs, s);
}
void mutt_group_context_add_adrlist (group_context_t *ctx, ADDRESS *a)
{
for (; ctx; ctx = ctx->next)
mutt_group_add_adrlist (ctx->g, a);
}
int mutt_group_context_remove_adrlist (group_context_t *ctx, ADDRESS * a)
{
int rv = 0;
for (; (!rv) && ctx; ctx = ctx->next)
{
rv = mutt_group_remove_adrlist (ctx->g, a);
if (empty_group (ctx->g))
mutt_group_remove (ctx->g, NULL);
}
return rv;
}
int mutt_group_context_add_rx (group_context_t *ctx, const char *s, int flags, BUFFER *err)
{
int rv = 0;
for (; (!rv) && ctx; ctx = ctx->next)
rv = mutt_group_add_rx (ctx->g, s, flags, err);
return rv;
}
int mutt_group_context_remove_rx (group_context_t *ctx, const char *s)
{
int rv = 0;
for (; (!rv) && ctx; ctx = ctx->next)
{
rv = mutt_group_remove_rx (ctx->g, s);
if (empty_group (ctx->g))
mutt_group_remove (ctx->g, NULL);
}
return rv;
}
int mutt_group_match (group_t *g, const char *s)
{
ADDRESS *ap;
if (s && g)
{
if (mutt_match_rx_list (s, g->rs))
......
/*
* Copyright (C) 2006 Thomas Roessler <[email protected]>
* Copyright (C) 2009 Rocco Rutte <[email protected]>
*
* 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.
*/
#ifndef _MUTT_GROUP_H_
#define _MUTT_GROUP_H_ 1
#define M_GROUP 0
#define M_UNGROUP 1
void mutt_group_add_adrlist (group_t *g, ADDRESS *a);
void mutt_group_context_add (group_context_t **ctx, group_t *group);
void mutt_group_context_destroy (group_context_t **ctx);
void mutt_group_context_add_adrlist (group_context_t *ctx, ADDRESS *a);
int mutt_group_context_add_rx (group_context_t *ctx, const char *s, int flags, BUFFER *err);
int mutt_group_match (group_t *g, const char *s);
int mutt_group_remove (group_t *, BUFFER *);
int mutt_group_context_remove_rx (group_context_t *ctx, const char *s);
int mutt_group_context_remove_adrlist (group_context_t *ctx, ADDRESS *);
#endif /* _MUTT_GROUP_H_ */
......@@ -31,6 +31,7 @@
#include "charset.h"
#include "mutt_crypt.h"
#include "mutt_idna.h"
#include "group.h"
#if defined(USE_SSL)
#include "mutt_ssl.h"
......@@ -833,60 +834,70 @@ static int parse_group (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
group_state_t state = NONE;
ADDRESS *addr = NULL;
char *estr = NULL;
do
do
{
mutt_extract_token (buf, s, 0);
if (parse_group_context (&gc, buf, s, data, err) == -1)
goto bail;
if (data == M_UNGROUP && !mutt_strcasecmp (buf->data, "*"))
{
if (mutt_group_remove (gc->g, err) < 0)
goto bail;
goto out;
}
if (!mutt_strcasecmp (buf->data, "-rx"))
state = RX;
else if (!mutt_strcasecmp (buf->data, "-addr"))
state = ADDR;
else
else
{
switch (state)
switch (state)
{
case NONE:
strfcpy (err->data, _("Missing -rx or -addr."), err->dsize);
snprintf (err->data, err->dsize, _("%sgroup: missing -rx or -addr."),
data == M_UNGROUP ? "un" : "");
goto bail;
case RX:
if (mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
if (data == M_GROUP &&
mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
goto bail;
else if (data == M_UNGROUP &&
mutt_group_context_remove_rx (gc, buf->data) < 0)
goto bail;
break;
case ADDR:
if ((addr = mutt_parse_adrlist (NULL, buf->data)) == NULL)
goto bail;
if (mutt_addrlist_to_idna (addr, &estr))
{
snprintf (err->data, err->dsize, _("Warning: Bad IDN '%s'.\n"),
estr);
if (mutt_addrlist_to_idna (addr, &estr))
{
snprintf (err->data, err->dsize, _("%sgroup: warning: bad IDN '%s'.\n"),
data == 1 ? "un" : "", estr);
goto bail;
}
mutt_group_context_add_adrlist (gc, addr);
if (data == M_GROUP)
mutt_group_context_add_adrlist (gc, addr);
else if (data == M_UNGROUP)
mutt_group_context_remove_adrlist (gc, addr);
rfc822_free_address (&addr);
break;
}
}
} while (MoreArgs (s));
out:
mutt_group_context_destroy (&gc);
return 0;
bail:
bail:
mutt_group_context_destroy (&gc);
return -1;
}
static int parse_ungroup (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
strfcpy (err->data, "not implemented", err->dsize);
return -1;
}
/* always wise to do what someone else did before */
static void _attachments_clean (void)
{
......
......@@ -3419,7 +3419,6 @@ static int parse_spam_list (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_unlist (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_group (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_ungroup (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_lists (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_unlists (BUFFER *, BUFFER *, unsigned long, BUFFER *);
......@@ -3472,8 +3471,8 @@ struct command_t Commands[] = {
{ "fcc-hook", mutt_parse_hook, M_FCCHOOK },
{ "fcc-save-hook", mutt_parse_hook, M_FCCHOOK | M_SAVEHOOK },
{ "folder-hook", mutt_parse_hook, M_FOLDERHOOK },
{ "group", parse_group, 0 },
{ "ungroup", parse_ungroup, 0 },
{ "group", parse_group, M_GROUP },
{ "ungroup", parse_group, M_UNGROUP },
{ "hdr_order", parse_list, UL &HeaderOrderList },
#ifdef HAVE_ICONV
{ "iconv-hook", mutt_parse_hook, M_ICONVHOOK },
......
......@@ -35,6 +35,7 @@
#include "mutt_crypt.h"
#include "mutt_curses.h"
#include "group.h"
#ifdef USE_IMAP
#include "mx.h"
......
......@@ -75,11 +75,6 @@ typedef const char * format_t (char *, size_t, size_t, char, const char *, const
void mutt_FormatString (char *, size_t, size_t, const char *, format_t *, unsigned long, format_flag);
void mutt_parse_content_type (char *, BODY *);
void mutt_generate_boundary (PARAMETER **);
void mutt_group_add_adrlist (group_t *, ADDRESS *);
void mutt_group_context_add (group_context_t **ctx, group_t *group);
void mutt_group_context_destroy (group_context_t **ctx);
void mutt_group_add_adrlist (group_t *g, ADDRESS *a);
void mutt_group_context_add_adrlist (group_context_t *ctx, ADDRESS *a);
void mutt_delete_parameter (const char *attribute, PARAMETER **p);
void mutt_set_parameter (const char *, const char *, PARAMETER **);
......@@ -311,8 +306,6 @@ int mutt_get_field_unbuffered (char *, char *, size_t, int);
#define mutt_get_password(A,B,C) mutt_get_field_unbuffered(A,B,C,M_PASS)
int mutt_get_postponed (CONTEXT *, HEADER *, HEADER **, char *, size_t);
int mutt_get_tmp_attachment (BODY *);
int mutt_group_match (group_t *g, const char *s);
int mutt_group_context_add_rx (group_context_t *ctx, const char *s, int flags, BUFFER *err);
int mutt_index_menu (void);
int mutt_invoke_sendmail (ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *, const char *, int);
int mutt_is_autoview (BODY *, const char *);
......
......@@ -82,6 +82,45 @@ static void rfc822_dequote_comment (char *s)
*w = 0;
}
static void free_address (ADDRESS *a)
{
FREE(&a->personal);
FREE(&a->mailbox);
#ifdef EXACT_ADDRESS
FREE(&a->val);
#endif
}
int rfc822_remove_from_adrlist (ADDRESS **a, const char *mailbox)
{
ADDRESS *p, *last = NULL, *t;
int rv = -1;
p = *a;
last = NULL;
while (p)
{
if (ascii_strcasecmp (mailbox, p->mailbox) == 0)
{
if (last)
last->next = p->next;
else
(*a) = p->next;
t = p;
p = p->next;
free_address (t);
rv = 0;
}
else
{
last = p;
p = p->next;
}
}
return (rv);
}
void rfc822_free_address (ADDRESS **p)
{
ADDRESS *t;
......
......@@ -57,6 +57,7 @@ void rfc822_write_address_single (char *, size_t, ADDRESS *, int);
void rfc822_free_address (ADDRESS **addr);
void rfc822_cat (char *, size_t, const char *, const char *);
int rfc822_valid_msgid (const char *msgid);
int rfc822_remove_from_adrlist (ADDRESS **a, const char *mailbox);
extern int RFC822Error;
extern const char *RFC822Errors[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment