/*
* Copyright (C) 2006 Thomas Roessler <roessler@does-not-exist.org>
- *
+ * Copyright (C) 2009 Rocco Rutte <pdmef@gmx.net>
+ *
* 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"
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));
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))
if ((*ctx)->g == group)
return;
}
-
+
*ctx = safe_calloc (1, sizeof (group_context_t));
(*ctx)->g = group;
}
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))
--- /dev/null
+/*
+ * Copyright (C) 2006 Thomas Roessler <roessler@does-not-exist.org>
+ * Copyright (C) 2009 Rocco Rutte <pdmef@gmx.net>
+ *
+ * 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_ */
#include "charset.h"
#include "mutt_crypt.h"
#include "mutt_idna.h"
+#include "group.h"
#if defined(USE_SSL)
#include "mutt_ssl.h"
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)
{
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 *);
{ "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 },
#include "mutt_crypt.h"
#include "mutt_curses.h"
+#include "group.h"
#ifdef USE_IMAP
#include "mx.h"
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 **);
#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 *);
*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;
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[];