summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-01-23 10:42:35 +0200
committerSergey Poznyakoff <gray@gnu.org>2019-01-23 10:51:00 +0200
commit5fbfaa6b81685e91a4407344ed7b2b221ce878f3 (patch)
treeaa4a5e103996fbb6faa639ca745c0fef938e65b6
parent6ea2ea5259553f5d8437e7fd8c7d4c15e7facfb0 (diff)
downloadmailutils-5fbfaa6b81685e91a4407344ed7b2b221ce878f3.tar.gz
mailutils-5fbfaa6b81685e91a4407344ed7b2b221ce878f3.tar.bz2
mail: improve message set parser
* mail/from.c (sender_string): New function. * mail/mail.h: Likewise. * mail/msgset.y: Fix memory management and error reporting. Implement sender address matching. * mail/util.c (util_outfolder_name): Always return allocated value. * mail/copy.c (mail_copy0): Add typecast.
-rw-r--r--NEWS6
-rw-r--r--mail/copy.c2
-rw-r--r--mail/from.c16
-rw-r--r--mail/mail.h1
-rw-r--r--mail/msgset.y100
-rw-r--r--mail/util.c2
6 files changed, 90 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 206e05323..5c50fa9d1 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,12 @@ Version 3.5.90 (git)
@ can be used with any command requring a mailbox name to refer to the
file given with the -f option.
+** Sender addresses in message sets
+
+Arbitrary string in message set is treated as sender address. It
+expands to all messages whose sender addresses as displayed in a header
+summary match the string.
+
** showenvelope
With the showenvelope variable set, mail incorrectly displayed
diff --git a/mail/copy.c b/mail/copy.c
index 967a0db1a..9732dbeb5 100644
--- a/mail/copy.c
+++ b/mail/copy.c
@@ -239,7 +239,7 @@ mail_copy0 (int argc, char **argv, int mark)
if (mail_expand_name (filename, &url))
return 1;
- filename = mu_url_to_string (url);
+ filename = (char*) mu_url_to_string (url);
if (mu_url_is_scheme (url, "file") || mu_url_is_scheme (url, "mbox"))
rc = append_to_file (filename, msglist, mark, &totals);
else
diff --git a/mail/from.c b/mail/from.c
index 2fc3bbb48..a9ee08f94 100644
--- a/mail/from.c
+++ b/mail/from.c
@@ -219,9 +219,8 @@ hdr_date (struct header_call_args *args, void *data)
return header_buf_string (args, date);
}
-/* %f */
-static char *
-hdr_from (struct header_call_args *args, void *data)
+char *
+sender_string (mu_message_t msg)
{
char *from = NULL;
@@ -229,7 +228,7 @@ hdr_from (struct header_call_args *args, void *data)
{
mu_header_t hdr;
- if (mu_message_get_header (args->msg, &hdr) == 0
+ if (mu_message_get_header (msg, &hdr) == 0
&& mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
{
mu_address_t address = NULL;
@@ -276,11 +275,18 @@ hdr_from (struct header_call_args *args, void *data)
mu_envelope_t env = NULL;
const char *sender = "";
- if (mu_message_get_envelope (args->msg, &env) == 0)
+ if (mu_message_get_envelope (msg, &env) == 0)
mu_envelope_sget_sender (env, &sender);
from = mu_strdup (sender);
}
+ return from;
+}
+/* %f */
+static char *
+hdr_from (struct header_call_args *args, void *data)
+{
+ char *from = sender_string (args->msg);
header_buf_string (args, from);
free (from);
return args->buf;
diff --git a/mail/mail.h b/mail/mail.h
index ec48f9e32..ee634c8ef 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -430,6 +430,7 @@ const char *util_url_to_string (mu_url_t url);
mu_stream_t open_pager (size_t lines);
void format_msgset (mu_stream_t str, const msgset_t *msgset, size_t *count);
+char *sender_string (mu_message_t msg);
int is_address_field (const char *name);
diff --git a/mail/msgset.y b/mail/msgset.y
index 4f41a85cc..8011dc779 100644
--- a/mail/msgset.y
+++ b/mail/msgset.y
@@ -44,12 +44,14 @@ static int select_type (mu_message_t msg, void *closure);
static int select_sender (mu_message_t msg, void *closure);
static int select_deleted (mu_message_t msg, void *closure);
static int check_set (msgset_t **pset);
-
+
int yyerror (const char *);
int yylex (void);
static int msgset_flags = MSG_NODELETED;
+static size_t message_count;
static msgset_t *result;
+static mu_opool_t tokpool;
%}
%union {
@@ -144,13 +146,23 @@ msg : header REGEXP /* /.../ */
hd.header = $1;
hd.expr = $2;
$$ = msgset_select (select_header, &hd, 0, 0);
- if ($1)
- free ($1);
- free ($2);
+ if (!$$)
+ {
+ if ($1)
+ mu_error (_("No applicable messages from {%s:/%s}"), $1, $2);
+ else
+ mu_error (_("No applicable messages from {/%s}"), $2);
+ YYERROR;
+ }
}
| BODY
{
$$ = msgset_select (select_body, $1, 0, 0);
+ if (!$$)
+ {
+ mu_error (_("No applicable messages from {:/%s}"), $1);
+ YYERROR;
+ }
}
| TYPE /* :n, :d, etc */
{
@@ -160,11 +172,20 @@ msg : header REGEXP /* /.../ */
YYERROR;
}
$$ = msgset_select (select_type, (void *)&$1, 0, 0);
+ if (!$$)
+ {
+ mu_error (_("No messages satisfy :%c"), $1);
+ YYERROR;
+ }
}
| IDENT /* Sender name */
{
$$ = msgset_select (select_sender, (void *)$1, 0, 0);
- free ($1);
+ if (!$$)
+ {
+ mu_error (_("No applicable messages from {%s}"), $1);
+ YYERROR;
+ }
}
;
@@ -211,6 +232,8 @@ range : number
;
number : partno
+ {
+ }
| partno '[' rangeset ']'
{
$$ = msgset_expand ($1, $3);
@@ -221,6 +244,12 @@ number : partno
partno : NUMBER
{
+ if ($1 > message_count)
+ {
+ util_error_range ($1);
+ YYERROR;
+ }
+
$$ = msgset_make_1 ($1);
}
| '(' rangeset ')'
@@ -279,14 +308,12 @@ yylex (void)
if (mu_isalpha (*cur_p))
{
char *p = cur_p;
- int len;
while (*cur_p && *cur_p != ',' && *cur_p != ':')
cur_p++;
- len = cur_p - p + 1;
- yylval.string = mu_alloc (len);
- memcpy (yylval.string, p, len-1);
- yylval.string[len-1] = 0;
+ mu_opool_append (tokpool, p, cur_p - p);
+ mu_opool_append_char (tokpool, 0);
+ yylval.string = mu_opool_finish (tokpool, NULL);
if (*cur_p == ':')
{
++cur_p;
@@ -298,16 +325,17 @@ yylex (void)
if (*cur_p == '/')
{
char *p = ++cur_p;
- int len;
while (*cur_p && *cur_p != '/')
cur_p++;
- len = cur_p - p + 1;
+
+ mu_opool_append (tokpool, p, cur_p - p);
+ mu_opool_append_char (tokpool, 0);
+ yylval.string = mu_opool_finish (tokpool, NULL);
+
if (*cur_p)
cur_p++;
- yylval.string = mu_alloc (len);
- memcpy (yylval.string, p, len-1);
- yylval.string[len-1] = 0;
+
return REGEXP;
}
@@ -317,16 +345,17 @@ yylex (void)
if (*cur_p == '/')
{
char *p = ++cur_p;
- int len;
-
+
while (*cur_p && *cur_p != '/')
cur_p++;
- len = cur_p - p + 1;
+
+ mu_opool_append (tokpool, p, cur_p - p);
+ mu_opool_append_char (tokpool, 0);
+ yylval.string = mu_opool_finish (tokpool, NULL);
+
if (*cur_p)
cur_p++;
- yylval.string = mu_alloc (len);
- memcpy (yylval.string, p, len-1);
- yylval.string[len-1] = 0;
+
return BODY;
}
if (*cur_p == 0)
@@ -348,10 +377,13 @@ msgset_parse (const int argc, char **argv, int flags, msgset_t **mset)
cur_ind = 1;
cur_p = NULL;
result = NULL;
+
+ mu_opool_create (&tokpool, MU_OPOOL_ENOMEMABRT);
+ mu_mailbox_messages_count (mbox, &message_count);
rc = yyparse ();
if (rc == 0)
{
- if (result == NULL)
+ if (!result)
{
util_noapp ();
rc = 1;
@@ -359,6 +391,7 @@ msgset_parse (const int argc, char **argv, int flags, msgset_t **mset)
else
*mset = result;
}
+ mu_opool_destroy (&tokpool);
return rc;
}
@@ -555,7 +588,7 @@ msgset_select (int (*sel) (mu_message_t, void *), void *closure, int rev,
for (i = total; i > 0; i--)
{
mu_mailbox_get_message (mbox, i, &msg);
- if ((*sel)(msg, closure))
+ if ((*sel) (msg, closure))
{
mp = msgset_make_1 (i);
if (!first)
@@ -573,7 +606,7 @@ msgset_select (int (*sel) (mu_message_t, void *), void *closure, int rev,
for (i = 1; i <= total; i++)
{
mu_mailbox_get_message (mbox, i, &msg);
- if ((*sel)(msg, closure))
+ if ((*sel) (msg, closure))
{
mp = msgset_make_1 (i);
if (!first)
@@ -686,13 +719,13 @@ select_body (mu_message_t msg, void *closure)
}
int
-select_sender (mu_message_t msg MU_ARG_UNUSED, void *closure MU_ARG_UNUSED)
+select_sender (mu_message_t msg, void *closure)
{
- /* char *sender = (char*) closure; */
- /* FIXME: all messages from sender argv[i] */
- /* Annoying we can use mu_address_create() for that
- but to compare against what? The email ? */
- return 0;
+ char *needle = (char*) closure;
+ char *sender = sender_string (msg);
+ int status = strcmp (sender, needle) == 0;
+ free (sender);
+ return status;
}
int
@@ -739,7 +772,12 @@ check_set (msgset_t **pset)
{
int flags = msgset_flags;
int rc = 0;
-
+
+ if (!*pset)
+ {
+ util_noapp ();
+ return 1;
+ }
if (msgset_count (*pset) == 1)
flags ^= MSG_SILENT;
if (flags & MSG_NODELETED)
diff --git a/mail/util.c b/mail/util.c
index f5471e77b..5611b84a3 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -677,6 +677,8 @@ util_outfolder_name (char *str)
}
free (s);
}
+ else
+ exp = mu_strdup (str);
break;
}

Return to:

Send suggestions and report system problems to the System administrator.