/*
* Copyright (C) 1996-2000 Michael R. Elkins <me@cs.hmc.edu>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifndef TESTING
#include "mutt.h"
#else
#define safe_strdup strdup
#define safe_malloc malloc
#define SKIPWS(x) while(isspace(*x))x++
#define FREE(x) safe_free(x)
#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
const char RFC822Specials[] = "@.,:;<>[]\\\"()";
#define is_special(x) strchr(RFC822Specials,x)
int RFC822Error = 0;
/* these must defined in the same order as the numerated errors given in rfc822.h */
const char *RFC822Errors[] = {
"out of memory",
"mismatched parenthesis",
"mismatched quotes",
"bad route in <>",
"bad address in <>",
"bad address spec"
};
void rfc822_dequote_comment (char *s)
{
char *w = s;
for (; *s; s++)
{
if (*s == '\\')
{
if (!*++s)
break; /* error? */
*w++ = *s;
}
else if (*s != '\"')
{
if (w != s)
*w = *s;
w++;
}
}
*w = 0;
}
void rfc822_free_address (ADDRESS **p)
{
ADDRESS *t;
while (*p)
{
t = *p;
*p = (*p)->next;
#ifdef EXACT_ADDRESS
FREE (&t->val);
#endif
FREE (&t->personal);
FREE (&t->mailbox);
FREE (&t);
}
}
static const char *
parse_comment (const char *s,
char *comment, size_t *commentlen, size_t commentmax)
{
int level = 1;
while (*s && level)
{
if (*s == '(')
level++;
else if (*s == ')')
{
if (--level == 0)
{
s++;
break;
}
}
else if (*s == '\\')
{
if (!*++s)
break;
}
if (*commentlen < commentmax)
comment[(*commentlen)++] = *s;
s++;
}
if (level)
{
RFC822Error = ERR_MISMATCH_PAREN;
return NULL;
}
return s;
}
static const char *
parse_quote (const char *s, char *token, size_t *tokenlen, size_t tokenmax)
{
if (*tokenlen < tokenmax)
token[(*tokenlen)++] = '"';
while (*s)
{
if (*tokenlen < tokenmax)
token[*tokenlen] = *s;
if (*s == '"')
return (s + 1);
if (*s == '\\')
{
if (!*++s)
break;
if (*tokenlen < tokenmax)
token[*tokenlen] = *s;
}
(*tokenlen)++;
s++;
}
RFC822Error = ERR_MISMATCH_QUOTE;
return NULL;
}
static const char *
next_token (const char *s, char *token, size_t *tokenlen, size_t tokenmax)
{
if (*s == '(')
return (parse_comment (s + 1, token, tokenlen, tokenmax));
if (*s == '"')
return (parse_quote (s + 1, token, tokenlen, tokenmax));
if (is_special (*s))
{
if (*tokenlen < tokenmax)
token[(*tokenlen)++] = *s;
return (s + 1);
}
while (*s)
{
if (ISSPACE (*s) || is_special (*s))
break;
if (*tokenlen < tokenmax)
token[(*tokenlen)++] = *s;
s++;
}
return s;
}
static const char *
parse_mailboxdomain (const char *s, const char *nonspecial,
char *mailbox, size_t *mailboxlen, size_t mailboxmax,
char *comment, size_t *commentlen, size_t commentmax)
{
const char *ps;
while (*s)
{
SKIPWS (s);
if (strchr (nonspecial, *s) == NULL && is_special (*s))
return s;
if (*s == '(')
{
if (*commentlen && *commentlen < commentmax)
comment[(*commentlen)++] = ' ';
ps = next_token (s, comment, commentlen, commentmax);
}
else
ps = next_token (s, mailbox, mailboxlen, mailboxmax);
if (!ps)
return NULL;
s = ps;
}
return s<