/*
+ * This code has been adapted from Mutt 1.5.16 which is
+ *
* Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- *
+ *
* 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"
-#endif
+ */
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
-#ifndef TESTING
-#include "mutt.h"
-#else
-#define safe_strdup strdup
-#define safe_malloc malloc
+#define safe_strdup xstrdup
+#define safe_malloc xmalloc
#define SKIPWS(x) while(isspace(*x))x++
-#define FREE(x) safe_free(x)
+#define FREE(x) free(*(x)), *(x) = NULL
#define ISSPACE isspace
#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}}
#define STRING 128
-#include "rfc822.h"
-#endif
-#include "mutt_idna.h"
+#include "util.h"
+#include "rfc822.h"
#define terminate_string(a, b, c) do { if ((b) < (c)) a[(b)] = 0; else \
a[(c)] = 0; } while (0)
#define terminate_buffer(a, b) terminate_string(a, b, sizeof (a) - 1)
-
const char RFC822Specials[] = "@.,:;<>[]\\\"()";
#define is_special(x) strchr(RFC822Specials,x)
"bad address spec"
};
-void rfc822_dequote_comment (char *s)
+static void rfc822_dequote_comment (char *s)
{
char *w = s;
{
t = *p;
*p = (*p)->next;
-#ifdef EXACT_ADDRESS
- FREE (&t->val);
-#endif
FREE (&t->personal);
FREE (&t->mailbox);
FREE (&t);
char *comment, size_t *commentlen, size_t commentmax)
{
int level = 1;
-
+
while (*s && level)
{
if (*s == '(')
char *comment, size_t *commentlen, size_t commentmax)
{
ADDRESS *cur = rfc822_new_address ();
-
+
if (parse_addr_spec (phrase, comment, commentlen, commentmax, cur) == NULL)
{
rfc822_free_address (&cur);
char comment[STRING], phrase[STRING];
size_t phraselen = 0, commentlen = 0;
ADDRESS *cur, *last = NULL;
-
+
RFC822Error = 0;
last = top;
last = last->next;
ws_pending = isspace ((unsigned char) *s);
-
+
SKIPWS (s);
begin = s;
while (*s)
last->personal = safe_strdup (comment);
}
-#ifdef EXACT_ADDRESS
- if (last && !last->val)
- last->val = mutt_substrdup (begin, s);
-#endif
commentlen = 0;
phraselen = 0;
s++;
top = cur;
last = cur;
-#ifdef EXACT_ADDRESS
- last->val = mutt_substrdup (begin, s);
-#endif
-
phraselen = 0;
commentlen = 0;
s++;
terminate_buffer (comment, commentlen);
last->personal = safe_strdup (comment);
}
-#ifdef EXACT_ADDRESS
- if (last && !last->val)
- last->val = mutt_substrdup (begin, s);
-#endif
/* add group terminator */
cur = rfc822_new_address ();
ws_pending = isspace ((unsigned char) *s);
SKIPWS (s);
}
-
+
if (phraselen)
{
terminate_buffer (phrase, phraselen);
terminate_buffer (comment, commentlen);
last->personal = safe_strdup (comment);
}
-#ifdef EXACT_ADDRESS
- if (last)
- last->val = mutt_substrdup (begin, s);
-#endif
return top;
}
-
-void rfc822_qualify (ADDRESS *addr, const char *host)
-{
- char *p;
-
- for (; addr; addr = addr->next)
- if (!addr->group && addr->mailbox && strchr (addr->mailbox, '@') == NULL)
- {
- p = safe_malloc (mutt_strlen (addr->mailbox) + mutt_strlen (host) + 2);
- sprintf (p, "%s@%s", addr->mailbox, host); /* __SPRINTF_CHECKED__ */
- FREE (&addr->mailbox);
- addr->mailbox = p;
- }
-}
-
-void
-rfc822_cat (char *buf, size_t buflen, const char *value, const char *specials)
-{
- if (strpbrk (value, specials))
- {
- char tmp[256], *pc = tmp;
- size_t tmplen = sizeof (tmp) - 3;
-
- *pc++ = '"';
- for (; *value && tmplen > 1; value++)
- {
- if (*value == '\\' || *value == '"')
- {
- *pc++ = '\\';
- tmplen--;
- }
- *pc++ = *value;
- tmplen--;
- }
- *pc++ = '"';
- *pc = 0;
- strfcpy (buf, tmp, buflen);
- }
- else
- strfcpy (buf, value, buflen);
-}
-
-void rfc822_write_address_single (char *buf, size_t buflen, ADDRESS *addr,
- int display)
-{
- size_t len;
- char *pbuf = buf;
- char *pc;
-
- if (!addr)
- return;
-
- buflen--; /* save room for the terminal nul */
-
-#ifdef EXACT_ADDRESS
- if (addr->val)
- {
- if (!buflen)
- goto done;
- strfcpy (pbuf, addr->val, buflen);
- len = mutt_strlen (pbuf);
- pbuf += len;
- buflen -= len;
- if (addr->group)
- {
- if (!buflen)
- goto done;
- *pbuf++ = ':';
- buflen--;
- *pbuf = 0;
- }
- return;
- }
-#endif
-
- if (addr->personal)
- {
- if (strpbrk (addr->personal, RFC822Specials))
- {
- if (!buflen)
- goto done;
- *pbuf++ = '"';
- buflen--;
- for (pc = addr->personal; *pc && buflen > 0; pc++)
- {
- if (*pc == '"' || *pc == '\\')
- {
- if (!buflen)
- goto done;
- *pbuf++ = '\\';
- buflen--;
- }
- if (!buflen)
- goto done;
- *pbuf++ = *pc;
- buflen--;
- }
- if (!buflen)
- goto done;
- *pbuf++ = '"';
- buflen--;
- }
- else
- {
- if (!buflen)
- goto done;
- strfcpy (pbuf, addr->personal, buflen);
- len = mutt_strlen (pbuf);
- pbuf += len;
- buflen -= len;
- }
-
- if (!buflen)
- goto done;
- *pbuf++ = ' ';
- buflen--;
- }
-
- if (addr->personal || (addr->mailbox && *addr->mailbox == '@'))
- {
- if (!buflen)
- goto done;
- *pbuf++ = '<';
- buflen--;
- }
-
- if (addr->mailbox)
- {
- if (!buflen)
- goto done;
- if (ascii_strcmp (addr->mailbox, "@") && !display)
- {
- strfcpy (pbuf, addr->mailbox, buflen);
- len = mutt_strlen (pbuf);
- }
- else if (ascii_strcmp (addr->mailbox, "@") && display)
- {
- strfcpy (pbuf, mutt_addr_for_display (addr), buflen);
- len = mutt_strlen (pbuf);
- }
- else
- {
- *pbuf = '\0';
- len = 0;
- }
- pbuf += len;
- buflen -= len;
-
- if (addr->personal || (addr->mailbox && *addr->mailbox == '@'))
- {
- if (!buflen)
- goto done;
- *pbuf++ = '>';
- buflen--;
- }
-
- if (addr->group)
- {
- if (!buflen)
- goto done;
- *pbuf++ = ':';
- buflen--;
- if (!buflen)
- goto done;
- *pbuf++ = ' ';
- buflen--;
- }
- }
- else
- {
- if (!buflen)
- goto done;
- *pbuf++ = ';';
- buflen--;
- }
-done:
- /* no need to check for length here since we already save space at the
- beginning of this routine */
- *pbuf = 0;
-}
-
-/* note: it is assumed that `buf' is nul terminated! */
-int rfc822_write_address (char *buf, size_t buflen, ADDRESS *addr, int display)
-{
- char *pbuf = buf;
- size_t len = mutt_strlen (buf);
-
- buflen--; /* save room for the terminal nul */
-
- if (len > 0)
- {
- if (len > buflen)
- return pbuf - buf; /* safety check for bogus arguments */
-
- pbuf += len;
- buflen -= len;
- if (!buflen)
- goto done;
- *pbuf++ = ',';
- buflen--;
- if (!buflen)
- goto done;
- *pbuf++ = ' ';
- buflen--;
- }
-
- for (; addr && buflen > 0; addr = addr->next)
- {
- /* use buflen+1 here because we already saved space for the trailing
- nul char, and the subroutine can make use of it */
- rfc822_write_address_single (pbuf, buflen + 1, addr, display);
-
- /* this should be safe since we always have at least 1 char passed into
- the above call, which means `pbuf' should always be nul terminated */
- len = mutt_strlen (pbuf);
- pbuf += len;
- buflen -= len;
-
- /* if there is another address, and its not a group mailbox name or
- group terminator, add a comma to separate the addresses */
- if (addr->next && addr->next->mailbox && !addr->group)
- {
- if (!buflen)
- goto done;
- *pbuf++ = ',';
- buflen--;
- if (!buflen)
- goto done;
- *pbuf++ = ' ';
- buflen--;
- }
- }
-done:
- *pbuf = 0;
- return pbuf - buf;
-}
-
-/* this should be rfc822_cpy_adr */
-ADDRESS *rfc822_cpy_adr_real (ADDRESS *addr)
-{
- ADDRESS *p = rfc822_new_address ();
-
-#ifdef EXACT_ADDRESS
- p->val = safe_strdup (addr->val);
-#endif
- p->personal = safe_strdup (addr->personal);
- p->mailbox = safe_strdup (addr->mailbox);
- p->group = addr->group;
- return p;
-}
-
-/* this should be rfc822_cpy_adrlist */
-ADDRESS *rfc822_cpy_adr (ADDRESS *addr)
-{
- ADDRESS *top = NULL, *last = NULL;
-
- for (; addr; addr = addr->next)
- {
- if (last)
- {
- last->next = rfc822_cpy_adr_real (addr);
- last = last->next;
- }
- else
- top = last = rfc822_cpy_adr_real (addr);
- }
- return top;
-}
-
-/* append list 'b' to list 'a' and return the last element in the new list */
-ADDRESS *rfc822_append (ADDRESS **a, ADDRESS *b)
-{
- ADDRESS *tmp = *a;
-
- while (tmp && tmp->next)
- tmp = tmp->next;
- if (!b)
- return tmp;
- if (tmp)
- tmp->next = rfc822_cpy_adr (b);
- else
- tmp = *a = rfc822_cpy_adr (b);
- while (tmp && tmp->next)
- tmp = tmp->next;
- return tmp;
-}
-
-/* incomplete. Only used to thwart the APOP MD5 attack (#2846). */
-int rfc822_valid_msgid (const char *msgid)
-{
- /* msg-id = "<" addr-spec ">"
- * addr-spec = local-part "@" domain
- * local-part = word *("." word)
- * word = atom / quoted-string
- * atom = 1*<any CHAR except specials, SPACE and CTLs>
- * CHAR = ( 0.-127. )
- * specials = "(" / ")" / "<" / ">" / "@"
- / "," / ";" / ":" / "\" / <">
- / "." / "[" / "]"
- * SPACE = ( 32. )
- * CTLS = ( 0.-31., 127.)
- * quoted-string = <"> *(qtext/quoted-pair) <">
- * qtext = <any CHAR except <">, "\" and CR>
- * CR = ( 13. )
- * quoted-pair = "\" CHAR
- * domain = sub-domain *("." sub-domain)
- * sub-domain = domain-ref / domain-literal
- * domain-ref = atom
- * domain-literal = "[" *(dtext / quoted-pair) "]"
- */
-
- char* dom;
- unsigned int l, i;
-
- if (!msgid || !*msgid)
- return -1;
-
- l = mutt_strlen (msgid);
- if (l < 5) /* <atom@atom> */
- return -1;
- if (msgid[0] != '<' || msgid[l-1] != '>')
- return -1;
- if (!(dom = strrchr (msgid, '@')))
- return -1;
-
- /* TODO: complete parser */
- for (i = 0; i < l; i++)
- if ((unsigned char)msgid[i] > 127)
- return -1;
-
- return 0;
-}
-
-#ifdef TESTING
-int safe_free (void **p) /* __SAFE_FREE_CHECKED__ */
-{
- free(*p); /* __MEM_CHECKED__ */
- *p = 0;
-}
-
-int main (int argc, char **argv)
-{
- ADDRESS *list;
- char buf[256];
-# if 0
- char *str = "michael, Michael Elkins <me@mutt.org>, testing a really complex address: this example <@contains.a.source.route,@with.multiple.hosts:address@example.com>;, lothar@of.the.hillpeople (lothar)";
-# else
- char *str = "a b c ";
-# endif
-
- list = rfc822_parse_adrlist (NULL, str);
- buf[0] = 0;
- rfc822_write_address (buf, sizeof (buf), list);
- rfc822_free_address (&list);
- puts (buf);
- exit (0);
-}
-#endif