Commit d971eaba d971eaba5417d3a06c332d1a6bf1929bb51f4d90 by Sergey Poznyakoff

Improve RFC822 address parsing.

* examples/addr.c: Allow to modify hints via command line (-v)
and within the shell (\...).
* include/mailutils/address.h (MU_ADDR_HINT_*): New defines.
(struct _mu_address): Definition.
(mu_address_create_hint): New prototype.
* include/mailutils/parse822.h (mu_parse822_address_list)
(mu_parse822_mail_box, mu_parse822_group)
(mu_parse822_address, mu_parse822_route_addr)
(mu_parse822_route, mu_parse822_addr_spec)
(mu_parse822_unix_mbox, mu_parse822_local_part): Take hint and hint flags.
* mailbox/parse822.c: Likewise.

* libproto/include/Makefile.am (noinst_HEADERS): Remove address0.h
* libproto/include/address0.h: Removed.
* mailbox/address.c (mu_address_create_hint): New function.
(mu_address_create): Rewrite using mu_address_create_hint.

* mh/mh_init.c (mh_expand_aliases): Use mu_header_sget_field_name
* mh/mh_whom.c (mh_alias_expand): Rewrite using mu_address_create_hint.
This fixes parsing addresses similar to "a@b <a@b>".
* mh/send.c: New command line option --preserve (--keep)
1 parent b1594c2a
......@@ -26,10 +26,14 @@
#include <mailutils/address.h>
#include <mailutils/errno.h>
#include <mailutils/kwd.h>
#include <mailutils/mutil.h>
#define EPARSE MU_ERR_NOENT
struct _mu_address hint;
int hflags;
static int
parse (const char *str)
{
......@@ -39,8 +43,7 @@ parse (const char *str)
const char *buf;
mu_address_t address = NULL;
mu_set_user_email_domain ("localhost");
status = mu_address_create (&address, str);
status = mu_address_create_hint (&address, str, &hint, hflags);
mu_address_get_count (address, &pcount);
if (status)
......@@ -96,6 +99,73 @@ parse (const char *str)
return 0;
}
struct mu_kwd hintnames[] = {
{ "comments", MU_ADDR_HINT_COMMENTS },
{ "personal", MU_ADDR_HINT_PERSONAL },
{ "email", MU_ADDR_HINT_EMAIL },
{ "local", MU_ADDR_HINT_LOCAL },
{ "domain", MU_ADDR_HINT_DOMAIN },
{ "route", MU_ADDR_HINT_ROUTE },
{ NULL }
};
static char **
addr_fieldptr_by_mask (mu_address_t addr, int mask)
{
switch (mask)
{
case MU_ADDR_HINT_ADDR:
return &addr->addr;
case MU_ADDR_HINT_COMMENTS:
return &addr->comments;
case MU_ADDR_HINT_PERSONAL:
return &addr->personal;
case MU_ADDR_HINT_EMAIL:
return &addr->email;
case MU_ADDR_HINT_LOCAL:
return &addr->local_part;
case MU_ADDR_HINT_DOMAIN:
return &addr->domain;
case MU_ADDR_HINT_ROUTE:
return &addr->route;
}
return NULL;
}
void
sethint (char *str)
{
int mask;
char *p = strchr (str, '=');
if (!p)
{
printf ("%s=> bad assignment\n\n", str);
return;
}
*p++ = 0;
if (mu_kwd_xlat_name (hintnames, str, &mask) == 0)
{
char **fptr = addr_fieldptr_by_mask (&hint, mask);
if (*p == 0)
hflags &= ~mask;
else
{
*fptr = strdup (p);
hflags |= mask;
}
}
else
printf ("%s=> unknown hint name\n\n", str);
}
static int
parseinput (void)
{
......@@ -104,26 +174,34 @@ parseinput (void)
while (fgets (buf, sizeof (buf), stdin) != 0)
{
buf[strlen (buf) - 1] = 0;
parse (buf);
if (buf[0] == '\\')
sethint (buf + 1);
else
parse (buf);
}
return 0;
}
int
main (int argc, const char *argv[])
main (int argc, char *argv[])
{
argc = 1;
if (!argv[argc])
int i;
hint.domain = "localhost";
hflags = MU_ADDR_HINT_DOMAIN;
if (argc == 1)
return parseinput ();
for (; argv[argc]; argc++)
for (i = 1; i < argc; i++)
{
if (strcmp (argv[argc], "-") == 0)
if (strcmp (argv[i], "-") == 0)
parseinput ();
else if (strncmp (argv[i], "-v", 2) == 0)
sethint (argv[i] + 2);
else
parse (argv[argc]);
parse (argv[i]);
}
return 0;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2005, 2006, 2007,
2009 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -25,6 +26,46 @@
extern "C" {
#endif
#define MU_ADDR_HINT_ADDR 0x0001 /* Not used yet */
#define MU_ADDR_HINT_COMMENTS 0x0002
#define MU_ADDR_HINT_PERSONAL 0x0004
#define MU_ADDR_HINT_EMAIL 0x0008
#define MU_ADDR_HINT_LOCAL 0x0010
#define MU_ADDR_HINT_DOMAIN 0x0020
#define MU_ADDR_HINT_ROUTE 0x0040
/*
* The data-structure representing an RFC822 MAILBOX. It may be
* one MAILBOX or a list of them, as found in an ADDRESS or
* a MAILBOX list (as found in a GROUP).
*
* Capitalized names are from RFC 822, section 6.1 (Address Syntax).
*/
struct _mu_address
{
char *addr;
/* the original string that this list of addresses was created
* from, only present at the head of the list */
char *comments;
/* the collection of comments stripped during parsing this MAILBOX */
char *personal;
/* the PHRASE portion of a MAILBOX, called the DISPLAY-NAME in drums */
char *email;
/* the ADDR-SPEC, the LOCAL-PART@DOMAIN */
char *local_part;
/* the LOCAL-PART of a MAILBOX */
char *domain;
/* the DOMAIN of a MAILBOX */
char *route;
/* the optional ROUTE in the ROUTE-ADDR form of MAILBOX */
struct _mu_address *next;
};
extern int mu_address_create_hint (mu_address_t *, const char *,
mu_address_t, int);
extern int mu_address_create (mu_address_t *, const char *);
extern int mu_address_createv (mu_address_t *, const char *v[], size_t);
extern void mu_address_destroy (mu_address_t *);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2005, 2007,
2009 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -49,57 +50,89 @@ extern int mu_parse822_is_q_text (char c);
extern int mu_parse822_is_d_text (char c);
extern int mu_parse822_is_smtp_q (char c);
extern int mu_parse822_skip_crlf (const char** p, const char* e);
extern int mu_parse822_skip_lwsp_char (const char** p, const char* e);
extern int mu_parse822_skip_lwsp (const char** p, const char* e);
extern int mu_parse822_skip_comments (const char** p, const char* e);
extern int mu_parse822_skip_nl (const char** p, const char* e);
extern int mu_parse822_digits (const char** p, const char* e, int min, int max, int* digits);
extern int mu_parse822_special (const char** p, const char* e, char c);
extern int mu_parse822_comment (const char** p, const char* e, char** comment);
extern int mu_parse822_atom (const char** p, const char* e, char** atom);
extern int mu_parse822_quoted_pair (const char** p, const char* e, char** qpair);
extern int mu_parse822_quoted_string (const char** p, const char* e, char** qstr);
extern int mu_parse822_word (const char** p, const char* e, char** word);
extern int mu_parse822_phrase (const char** p, const char* e, char** phrase);
extern int mu_parse822_d_text (const char** p, const char* e, char** dtext);
extern int mu_parse822_skip_crlf (const char **p, const char *e);
extern int mu_parse822_skip_lwsp_char (const char **p, const char *e);
extern int mu_parse822_skip_lwsp (const char **p, const char *e);
extern int mu_parse822_skip_comments (const char **p, const char *e);
extern int mu_parse822_skip_nl (const char **p, const char *e);
extern int mu_parse822_digits (const char **p, const char *e,
int min, int max, int *digits);
extern int mu_parse822_special (const char **p, const char *e, char c);
extern int mu_parse822_comment (const char **p, const char *e,
char **comment);
extern int mu_parse822_atom (const char **p, const char *e,
char **atom);
extern int mu_parse822_quoted_pair (const char **p, const char *e,
char **qpair);
extern int mu_parse822_quoted_string (const char **p, const char *e,
char **qstr);
extern int mu_parse822_word (const char **p, const char *e,
char **word);
extern int mu_parse822_phrase (const char **p, const char *e,
char **phrase);
extern int mu_parse822_d_text (const char **p, const char *e,
char **dtext);
/* From RFC 822, 6.1 Address Specification Syntax */
extern int mu_parse822_address_list (mu_address_t* a, const char* s);
extern int mu_parse822_mail_box (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_group (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_address (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_route_addr (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_route (const char** p, const char* e, char** route);
extern int mu_parse822_addr_spec (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_unix_mbox (const char** p, const char* e, mu_address_t* a);
extern int mu_parse822_local_part (const char** p, const char* e, char** local_part);
extern int mu_parse822_domain (const char** p, const char* e, char** domain);
extern int mu_parse822_sub_domain (const char** p, const char* e, char** sub_domain);
extern int mu_parse822_domain_ref (const char** p, const char* e, char** domain_ref);
extern int mu_parse822_domain_literal (const char** p, const char* e, char** domain_literal);
extern int mu_parse822_address_list (mu_address_t *a, const char *s,
mu_address_t hint, int hflags);
extern int mu_parse822_mail_box (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_group (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_address (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_route_addr (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_route (const char **p, const char *e,
char **route);
extern int mu_parse822_addr_spec (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_unix_mbox (const char **p, const char *e,
mu_address_t *a,
mu_address_t hint, int hflags);
extern int mu_parse822_local_part (const char **p, const char *e,
char **local_part);
extern int mu_parse822_domain (const char **p, const char *e,
char **domain);
extern int mu_parse822_sub_domain (const char **p, const char *e,
char **sub_domain);
extern int mu_parse822_domain_ref (const char **p, const char *e,
char **domain_ref);
extern int mu_parse822_domain_literal (const char **p, const char *e,
char **domain_literal);
/* RFC 822 Quoting Functions
* Various elements must be quoted if then contain non-safe characters. What
* characters are allowed depend on the element. The following functions will
* allocate a quoted version of the raw element, it may not actually be
* quoted if no unsafe characters were in the raw string.
*/
* Various elements must be quoted if then contain non-safe characters. What
* characters are allowed depend on the element. The following functions will
* allocate a quoted version of the raw element, it may not actually be
* quoted if no unsafe characters were in the raw string.
*/
extern int mu_parse822_quote_string (char** quoted, const char* raw);
extern int mu_parse822_quote_local_part (char** quoted, const char* raw);
extern int mu_parse822_quote_string (char **quoted, const char *raw);
extern int mu_parse822_quote_local_part (char **quoted, const char *raw);
extern int mu_parse822_field_body (const char** p, const char *e, char** fieldbody);
extern int mu_parse822_field_name (const char** p, const char *e, char** fieldname);
extern int mu_parse822_field_body (const char **p, const char *e,
char **fieldbody);
extern int mu_parse822_field_name (const char **p, const char *e,
char **fieldname);
/***** From RFC 822, 5.1 Date and Time Specification Syntax *****/
extern int mu_parse822_day (const char** p, const char* e, int* day);
extern int mu_parse822_date (const char** p, const char* e, int* day, int* mon, int* year);
extern int mu_parse822_time (const char** p, const char* e, int* h, int* m, int* s, int* tz, const char** tz_name);
extern int mu_parse822_date_time (const char** p, const char* e, struct tm* tm, mu_timezone* tz);
extern int mu_parse822_day (const char **p, const char *e, int *day);
extern int mu_parse822_date (const char **p, const char *e, int *day,
int *mon, int *year);
extern int mu_parse822_time (const char **p, const char *e, int *h,
int *m, int *s, int *tz, const char **tz_name);
extern int mu_parse822_date_time (const char **p, const char *e,
struct tm *tm, mu_timezone *tz);
#ifdef __cplusplus
......
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
## Copyright (C) 2000, 2001, 2002, 2007,
## 2009 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
......@@ -18,7 +19,6 @@
## 02110-1301 USA
noinst_HEADERS = \
address0.h \
attribute0.h \
amd.h \
auth0.h \
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifndef _ADDRESS0_H
#define _ADDRESS0_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/address.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The data-structure representing an RFC822 MAILBOX. It may be
* one MAILBOX or a list of them, as found in an ADDRESS or
* a MAILBOX list (as found in a GROUP).
*
* Capitalized names are from RFC 822, section 6.1 (Address Syntax).
*/
struct _mu_address
{
char *addr;
/* the original string that this list of addresses was created
* from, only present at the head of the list */
char *comments;
/* the collection of comments stripped during parsing this MAILBOX */
char *personal;
/* the PHRASE portion of a MAILBOX, called the DISPLAY-NAME in drums */
char *email;
/* the ADDR-SPEC, the LOCAL-PART@DOMAIN */
char *local_part;
/* the LOCAL-PART of a MAILBOX */
char *domain;
/* the DOMAIN of a MAILBOX */
char *route;
/* the optional ROUTE in the ROUTE-ADDR form of MAILBOX */
struct _mu_address *next;
};
#ifdef __cplusplus
}
#endif
#endif /* _ADDRESS0_H */
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2005, 2006,
2007 Free Software Foundation, Inc.
2007, 2009 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -34,12 +34,12 @@
#include <mailutils/errno.h>
#include <mailutils/mutil.h>
#include <mailutils/parse822.h>
#include <address0.h>
#include <mailutils/address.h>
/* Get email addresses from rfc822 address. */
int
mu_address_create (mu_address_t * a, const char *s)
mu_address_create_hint (mu_address_t *a, const char *s, mu_address_t hint,
int hflags)
{
/* 'a' must exist, and can't already have been initialized
*/
......@@ -52,7 +52,7 @@ mu_address_create (mu_address_t * a, const char *s)
return EINVAL;
*a = NULL;
status = mu_parse822_address_list (a, s);
status = mu_parse822_address_list (a, s, hint, hflags);
if (status == 0)
{
/* And address-list may contain 0 addresses but parse correctly.
......@@ -70,9 +70,20 @@ mu_address_create (mu_address_t * a, const char *s)
return status;
}
/* Get email addresses from array of rfc822 addresses. */
int
mu_address_createv (mu_address_t * a, const char *sv[], size_t len)
mu_address_create (mu_address_t *a, const char *s)
{
struct _mu_address hint;
const char *d;
mu_get_user_email_domain (&d);
hint.domain = (char*) d;
return mu_address_create_hint (a, s, &hint, MU_ADDR_HINT_DOMAIN);
}
/* Get email addresses from array of rfc822 addresses.
FIXME: No hints? */
int
mu_address_createv (mu_address_t *a, const char *sv[], size_t len)
{
int status = 0;
size_t buflen = 0;
......@@ -130,7 +141,7 @@ mu_address_createv (mu_address_t * a, const char *sv[], size_t len)
}
void
mu_address_destroy (mu_address_t * paddress)
mu_address_destroy (mu_address_t *paddress)
{
if (paddress && *paddress)
{
......@@ -160,7 +171,7 @@ mu_address_destroy (mu_address_t * paddress)
}
int
mu_address_concatenate (mu_address_t to, mu_address_t * from)
mu_address_concatenate (mu_address_t to, mu_address_t *from)
{
if (!to || !from || !*from)
return EINVAL;
......@@ -254,7 +265,6 @@ ACCESSOR(sget,field) (mu_address_t addr, size_t no, char const **sptr) \
subaddr = _address_get_nth (addr, no); \
if (!subaddr) \
return MU_ERR_NOENT; \
\
*sptr = subaddr->field; \
return 0; \
}
......@@ -262,7 +272,7 @@ ACCESSOR(sget,field) (mu_address_t addr, size_t no, char const **sptr) \
#define DECL_GET(field) \
int \
ACCESSOR(get,field) (mu_address_t addr, size_t no, char *buf, size_t len, \
size_t * n) \
size_t *n) \
{ \
size_t i; \
const char *str; \
......@@ -429,7 +439,7 @@ mu_address_is_group (mu_address_t addr, size_t no, int *yes)
}
int
mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t * n)
mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t *n)
{
size_t i;
if (addr == NULL)
......@@ -453,7 +463,7 @@ mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t * n)
}
int
mu_address_get_count (mu_address_t addr, size_t * pcount)
mu_address_get_count (mu_address_t addr, size_t *pcount)
{
size_t j;
for (j = 0; addr; addr = addr->next, j++)
......@@ -464,7 +474,7 @@ mu_address_get_count (mu_address_t addr, size_t * pcount)
}
int
mu_address_get_group_count (mu_address_t addr, size_t * pcount)
mu_address_get_group_count (mu_address_t addr, size_t *pcount)
{
size_t j;
for (j = 0; addr; addr = addr->next)
......@@ -478,7 +488,7 @@ mu_address_get_group_count (mu_address_t addr, size_t * pcount)
}
int
mu_address_get_email_count (mu_address_t addr, size_t * pcount)
mu_address_get_email_count (mu_address_t addr, size_t *pcount)
{
size_t j;
for (j = 0; addr; addr = addr->next)
......@@ -492,7 +502,7 @@ mu_address_get_email_count (mu_address_t addr, size_t * pcount)
}
int
mu_address_get_unix_mailbox_count (mu_address_t addr, size_t * pcount)
mu_address_get_unix_mailbox_count (mu_address_t addr, size_t *pcount)
{
size_t j;
for (j = 0; addr; addr = addr->next)
......@@ -522,6 +532,11 @@ mu_address_dup (mu_address_t src)
if (!dst)
return NULL;
/* FIXME: How about:
if (src->addr)
dst->addr = strdup (src->addr);
?
*/
if (src->comments)
dst->comments = strdup (src->comments);
if (src->personal)
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2005, 2007,
2009 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -87,10 +88,9 @@ actually help.
# include <strings.h>
#endif
#include "address0.h"
#include <mailutils/errno.h>
#include <mailutils/parse822.h>
#include <mailutils/address.h>
#ifdef EOK
# undef EOK
......@@ -478,7 +478,7 @@ mu_parse822_atom (const char **p, const char *e, char **atom)
save = *p;
while ((*p != e) && mu_parse822_is_atom_char (**p))
while ((*p != e) && (**p == '.' || mu_parse822_is_atom_char (**p)))
{
rc = str_append_char (atom, **p);
*p += 1;
......@@ -495,24 +495,18 @@ int
parse822_atom_ex (const char **p, const char *e, char **atom)
{
/* atom = 1*<an atom char> */
const char *save = *p;
int rc = EPARSE;
const char *ptr;
int rc;
mu_parse822_skip_comments (p, e);
save = *p;
while ((*p != e) && parse822_is_atom_char_ex (**p))
{
rc = str_append_char (atom, **p);
*p += 1;
if (rc != EOK)
{
*p = save;
break;
}
}
for (ptr = *p; (ptr != e) && parse822_is_atom_char_ex (*ptr); ptr++)
;
if (ptr - *p == 0)
return EPARSE;
rc = str_append_n (atom, *p, ptr - *p);
if (rc == 0)
*p = ptr;
return rc;
}
......@@ -714,59 +708,133 @@ new_mb (void)
return calloc (1, sizeof (struct _mu_address));
}
static char *
addr_field_by_mask (mu_address_t addr, int mask)
{
switch (mask)
{
case MU_ADDR_HINT_ADDR:
return addr->addr;
case MU_ADDR_HINT_COMMENTS:
return addr->comments;
case MU_ADDR_HINT_PERSONAL:
return addr->personal;
case MU_ADDR_HINT_EMAIL:
return addr->email;
case MU_ADDR_HINT_LOCAL:
return addr->local_part;
case MU_ADDR_HINT_DOMAIN:
return addr->domain;
case MU_ADDR_HINT_ROUTE:
return addr->route;
}
return NULL;
}
static char *
get_val (mu_address_t hint, int hflags, char *value, int mask, int *memflag)
{
if (!value && hint && (hflags & mask))
{
char *p = addr_field_by_mask (hint, mask);
if (p)
{
if (memflag)
*memflag |= mask;
value = strdup (p);
}
}
return value;
}
static void
addr_free_fields (mu_address_t a, int memflag)
{
char *p;
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_ADDR)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_COMMENTS)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_PERSONAL)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_EMAIL)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_LOCAL)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_DOMAIN)))
free (p);
if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_ROUTE)))
free (p);
}
static int
fill_mb (mu_address_t * a,
char *comments, char *personal, char *local, char *domain)
fill_mb (mu_address_t *pa,
char *comments, char *personal, char *local, char *domain,
mu_address_t hint, int hflags)
{
int rc = EOK;
mu_address_t a;
int memflag = 0;
*a = new_mb ();
a = new_mb ();
if (!*a)
{
return ENOMEM;
}
if (!a)
return ENOMEM;
(*a)->comments = comments;
(*a)->personal = personal;
a->comments = get_val (hint, hflags, comments, MU_ADDR_HINT_COMMENTS,
&memflag);
a->personal = get_val (hint, hflags, personal, MU_ADDR_HINT_PERSONAL,
&memflag);
domain = get_val (hint, hflags, domain, MU_ADDR_HINT_DOMAIN,
&memflag);
local = get_val (hint, hflags, local, MU_ADDR_HINT_LOCAL,
&memflag);
do
{
/* loop exists only to break out of */
const char *d = domain;
if (!d)
{
mu_get_user_email_domain (&d);
}
if (!local || !d)
{
/* no email to construct */
break;
}
if ((rc = mu_parse822_quote_local_part (&(*a)->email, local)))
break;
if ((rc = str_append (&(*a)->email, "@")))
if (!local)
/* no email to construct */
break;
if ((rc = str_append (&(*a)->email, d)))
if ((rc = mu_parse822_quote_local_part (&a->email, local)))
break;
if (domain)
{
if ((rc = str_append (&a->email, "@")))
break;
if ((rc = str_append (&a->email, domain)))
break;
}
}
while (0);
(*a)->local_part = local;
(*a)->domain = domain;
a->local_part = local;
a->domain = domain;
if (rc != EOK)
{
addr_free_fields (a, memflag);
/* note that the arguments have NOT been freed, we only own
* them on success. */
free (*a);
free (a);
}
else
*pa = a;
return rc;
}
int
mu_parse822_address_list (mu_address_t * a, const char *s)
mu_parse822_address_list (mu_address_t *a, const char *s,
mu_address_t hint, int hflags)
{
/* address-list = #(address) */
......@@ -775,7 +843,7 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
int rc = EOK;
mu_address_t *n = a; /* the next address we'll be creating */
rc = mu_parse822_address (p, e, n);
rc = mu_parse822_address (p, e, n, hint, hflags);
/* A list may start with a leading <,>, we'll find out if
* that's not the case at the top of the while, but give
......@@ -808,7 +876,7 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
}
mu_parse822_skip_comments (p, e);
rc = mu_parse822_address (p, e, n);
rc = mu_parse822_address (p, e, n, hint, hflags);
if (rc == EOK || rc == EPARSE)
{
......@@ -833,20 +901,24 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
}
int
mu_parse822_address (const char **p, const char *e, mu_address_t * a)
mu_parse822_address (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* address = mailbox / group / unix-mbox */
int rc;
if ((rc = mu_parse822_mail_box (p, e, a)) == EPARSE)
if ((rc = mu_parse822_mail_box (p, e, a, hint, hflags)) == EPARSE)
{
if ((rc = mu_parse822_group (p, e, a)) == EPARSE)
if ((rc = mu_parse822_group (p, e, a, hint, hflags)) == EPARSE)
{
rc = mu_parse822_unix_mbox (p, e, a);
rc = mu_parse822_unix_mbox (p, e, a, hint, hflags);
}
}
if (rc == 0 && *a && !(*a)->route)
(*a)->route = get_val (hint, hflags, NULL, MU_ADDR_HINT_ROUTE, NULL);
return rc;
}
......@@ -856,7 +928,8 @@ mu_parse822_address (const char **p, const char *e, mu_address_t * a)
*/
#undef ADD_GROUPS
int
mu_parse822_group (const char **p, const char *e, mu_address_t * a)
mu_parse822_group (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* group = phrase ":" [#mailbox] ";" */
......@@ -886,7 +959,7 @@ mu_parse822_group (const char **p, const char *e, mu_address_t * a)
/* fake up an address node for the group's descriptive phrase, if
* it fails, clean-up will happen after the loop
*/
if ((rc = fill_mb (a, 0, phrase, 0, 0)) == EOK)
if ((rc = fill_mb (a, 0, phrase, 0, 0, hint, hflags)) == EOK)
{
a = &(*a)->next;
}
......@@ -907,7 +980,7 @@ mu_parse822_group (const char **p, const char *e, mu_address_t * a)
mu_parse822_skip_comments (p, e);
/* it's ok not be a mailbox, but other errors are fatal */
rc = mu_parse822_mail_box (p, e, a);
rc = mu_parse822_mail_box (p, e, a, hint, hflags);
if (rc == EOK)
{
a = &(*a)->next;
......@@ -941,7 +1014,8 @@ mu_parse822_group (const char **p, const char *e, mu_address_t * a)
}
int
mu_parse822_mail_box (const char **p, const char *e, mu_address_t * a)
mu_parse822_mail_box (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* mailbox =
* addr-spec [ "(" comment ")" ] /
......@@ -956,7 +1030,7 @@ mu_parse822_mail_box (const char **p, const char *e, mu_address_t * a)
int rc;
/* -> addr-spec */
if ((rc = mu_parse822_addr_spec (p, e, a)) == EOK)
if ((rc = mu_parse822_addr_spec (p, e, a, hint, hflags)) == EOK)
{
mu_parse822_skip_lwsp (p, e);
......@@ -987,7 +1061,7 @@ mu_parse822_mail_box (const char **p, const char *e, mu_address_t * a)
return rc;
}
if ((rc = mu_parse822_route_addr (p, e, a)) == EOK)
if ((rc = mu_parse822_route_addr (p, e, a, hint, hflags)) == EOK)
{
/* add the phrase */
(*a)->personal = phrase;
......@@ -1005,14 +1079,16 @@ mu_parse822_mail_box (const char **p, const char *e, mu_address_t * a)
}
int
mu_parse822_route_addr (const char **p, const char *e, mu_address_t * a)
mu_parse822_route_addr (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* route-addr = "<" [route] addr-spec ">" */
const char *save = *p;
char *route = 0;
char *route = NULL;
int rc;
int memflag = 0;
mu_parse822_skip_comments (p, e);
if ((rc = mu_parse822_special (p, e, '<')))
......@@ -1023,15 +1099,15 @@ mu_parse822_route_addr (const char **p, const char *e, mu_address_t * a)
}
if (!(rc = mu_parse822_special (p, e, '>')))
{
(void) (((rc = fill_mb (a, 0, 0, 0, 0)) == EOK)
&& ((rc = str_append (&(*a)->email, "")) == EOK));
if ((rc = fill_mb (a, 0, 0, 0, 0, hint, hflags)) == EOK)
rc = str_append (&(*a)->email, "");
return rc;
}
mu_parse822_route (p, e, &route);
if ((rc = mu_parse822_addr_spec (p, e, a)))
if ((rc = mu_parse822_addr_spec (p, e, a, hint, hflags)))
{
*p = save;
......@@ -1040,7 +1116,8 @@ mu_parse822_route_addr (const char **p, const char *e, mu_address_t * a)
return rc;
}
(*a)->route = route; /* now we don't have to free our local */
(*a)->route = get_val (hint, hflags, route, MU_ADDR_HINT_ROUTE,
&memflag);
mu_parse822_skip_comments (p, e);
......@@ -1121,7 +1198,8 @@ mu_parse822_route (const char **p, const char *e, char **route)
}
int
mu_parse822_addr_spec (const char **p, const char *e, mu_address_t * a)
mu_parse822_addr_spec (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* addr-spec = local-part "@" domain */
......@@ -1137,18 +1215,16 @@ mu_parse822_addr_spec (const char **p, const char *e, mu_address_t * a)
if (!rc)
{
rc = mu_parse822_special (p, e, '@');
}
if (!rc)
{
rc = mu_parse822_domain (p, e, &domain);
}
if (!rc)
{
rc = mu_parse822_domain (p, e, &domain);
if (!rc)
{
rc = fill_mb (a, 0, 0, local_part, domain);
if (!rc)
rc = fill_mb (a, 0, 0, local_part, domain, hint, hflags);
}
}
if (rc)
{
*p = save;
......@@ -1159,7 +1235,8 @@ mu_parse822_addr_spec (const char **p, const char *e, mu_address_t * a)
}
int
mu_parse822_unix_mbox (const char **p, const char *e, mu_address_t * a)
mu_parse822_unix_mbox (const char **p, const char *e, mu_address_t *a,
mu_address_t hint, int hflags)
{
/* unix-mbox = atom */
......@@ -1172,9 +1249,7 @@ mu_parse822_unix_mbox (const char **p, const char *e, mu_address_t * a)
rc = mu_parse822_atom (p, e, &mbox);
if (!rc)
{
rc = fill_mb (a, 0, 0, mbox, 0);
}
rc = fill_mb (a, 0, 0, mbox, 0, hint, hflags);
if (rc)
{
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2003,
2005, 2006, 2007 Free Software Foundation, Inc.
2005, 2006, 2007, 2009 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -931,13 +931,13 @@ mh_expand_aliases (mu_message_t msg,
{
mu_header_t hdr;
size_t i, num;
char *buf;
const char *buf;
mu_message_get_header (msg, &hdr);
mu_header_get_field_count (hdr, &num);
for (i = 1; i <= num; i++)
{
if (mu_header_aget_field_name (hdr, i, &buf) == 0)
if (mu_header_sget_field_name (hdr, i, &buf) == 0)
{
if (strcasecmp (buf, MU_HEADER_TO) == 0
|| strcasecmp (buf, MU_HEADER_CC) == 0
......@@ -958,7 +958,6 @@ mh_expand_aliases (mu_message_t msg,
else if (strcasecmp (buf, MU_HEADER_BCC) == 0)
mu_address_union (addr_bcc ? addr_bcc : addr_to, addr);
}
free (buf);
}
}
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2003, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -51,69 +51,47 @@ ismydomain (char *p)
return strcasecmp (domain, p + 1) == 0;
}
/* FIXME: incl is not used */
int
mh_alias_expand (const char *str, mu_address_t *paddr, int *incl)
{
int argc;
char **argv;
int i;
char *buf;
mu_address_t exaddr = NULL;
size_t i, count;
mu_address_t addr;
int status;
if (incl)
*incl = 0;
mu_argcv_get (str, ",", NULL, &argc, &argv);
for (i = 0; i < argc;)
status = mu_address_create_hint (&addr, str, NULL, 0);
if (status)
{
if (i + 1 == argc)
{
if (mh_alias_get_address (argv[i], &exaddr, incl) == 0)
{
free (argv[i]);
memcpy (&argv[i], &argv[i+1],
(argc - i + 1) * sizeof (argv[0]));
argc--;
}
else
i++;
}
else if (argv[i + 1][0] == ',')
mu_error (_("Bad address `%s': %s"), str, mu_strerror (status));
return 1;
}
mu_address_get_count (addr, &count);
for (i = 1; i <= count; i++)
{
mu_address_t subaddr = NULL;
const char *key;
if (mu_address_sget_domain (addr, i, &key) == 0 && key == NULL)
{
if (mh_alias_get_address (argv[i], &exaddr, incl) == 0)
{
free (argv[i]);
free (argv[i+1]);
memcpy (&argv[i], &argv[i+2],
(argc - i) * sizeof (argv[0]));
argc -= 2;
}
else
i += 2;
if (mu_address_sget_local_part (addr, i, &key) == 0
&& mh_alias_get_address (key, paddr, incl) == 0)
continue;
}
else
status = mu_address_get_nth (addr, i, &subaddr);
if (status)
{
for (; i < argc; i++)
if (argv[i][0] == ',')
{
i++;
break;
}
mu_error (_("%s: cannot get address #%lu: %s"),
str, (unsigned long) i, mu_strerror (status));
continue;
}
}
if (argc)
{
int status;
mu_argcv_string (argc, argv, &buf);
if ((status = mu_address_create (paddr, buf)))
mu_error (_("Bad address `%s': %s"), buf, mu_strerror (status));
free (buf);
mu_address_union (paddr, subaddr);
mu_address_destroy (&subaddr);
}
mu_argcv_free (argc, argv);
mu_address_union (paddr, exaddr);
mu_address_destroy (&exaddr);
return 0;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 2003, 2005, 2006, 2007, 2008,
2009 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -61,6 +62,9 @@ static struct argp_option options[] = {
{"push", ARG_PUSH, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("Run in the backround.") },
{"nopush", ARG_NOPUSH, NULL, OPTION_HIDDEN, "" },
{"preserve", ARG_PRESERVE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("Keep draft files") },
{"keep", 0, NULL, OPTION_ALIAS, NULL},
{"split", ARG_SPLIT, N_("SECONDS"), 0,
N_("Split the draft into several partial messages and send them with SECONDS interval") },
{"chunksize", ARG_CHUNKSIZE, N_("NUMBER"), 0,
......@@ -91,7 +95,9 @@ struct mh_option mh_option[] = {
{"forward", 4, MH_OPT_BOOL, NULL},
{"mime", 2, MH_OPT_BOOL, NULL},
{"msgid", 2, MH_OPT_BOOL, NULL},
{"push", 1, MH_OPT_BOOL, NULL},
{"push", 2, MH_OPT_BOOL, NULL},
{"preserve", 2, MH_OPT_BOOL, NULL},
{"keep", 1, MH_OPT_BOOL, NULL},
{"split", 1, 0, "seconds"},
{"verbose", 1, MH_OPT_BOOL, NULL},
{"watch", 2, MH_OPT_BOOL, NULL},
......@@ -116,6 +122,8 @@ static int verbose; /* Produce verbose diagnostics */
static int watch; /* Watch the delivery process */
static unsigned width = 76; /* Maximum width of header fields */
static int keep_files; /* Keep draft files */
#define DEFAULT_X_MAILER "MH (" PACKAGE_STRING ")"
#define WATCH(c) do {\
......@@ -196,6 +204,10 @@ opt_handler (int key, char *arg, void *unused, struct argp_state *state)
case ARG_NOMSGID:
append_msgid = 0;
break;
case ARG_PRESERVE:
keep_files = is_true (arg);
break;
case ARG_PUSH:
background = is_true (arg);
......@@ -690,7 +702,8 @@ _action_send (void *item, void *data)
mu_mailer_close (mailer);
mu_mailer_destroy (&mailer);
backup_file (elt->file_name);
if (!keep_files)
backup_file (elt->file_name);
return 0;
}
......