common: Add function is_valid_mailbox_mem.

* common/mbox-util.c (mem_count_chr): New.
(my_memstr): New.
(has_invalid_email_chars): Change args to work on a buffer.
(is_valid_mailbox_mem): New.
(is_valid_mailbox): Rewrite to use is_valid_mailbox_mem.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-03-20 15:39:49 +01:00
parent 783a4a9837
commit a0eb2e4e8c
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 82 additions and 26 deletions

View File

@ -50,6 +50,47 @@ string_count_chr (const char *string, int c)
return count;
}
static int
mem_count_chr (const void *buffer, int c, size_t length)
{
const char *s = buffer;
int count;
for (count=0; length; length--, s++)
if (*s == c)
count++;
return count;
}
/* This is a case-sensitive version of our memistr. I wonder why no
standard function memstr exists but I better do not use the name
memstr to avoid future conflicts. */
static const char *
my_memstr (const void *buffer, size_t buflen, const char *sub)
{
const unsigned char *buf = buffer;
const unsigned char *t = (const unsigned char *)buf;
const unsigned char *s = (const unsigned char *)sub;
size_t n = buflen;
for ( ; n ; t++, n-- )
{
if (*t == *s)
{
for (buf = t++, buflen = n--, s++; n && *t ==*s; t++, s++, n--)
;
if (!*s)
return (const char*)buf;
t = (const unsigned char *)buf;
s = (const unsigned char *)sub ;
n = buflen;
}
}
return NULL;
}
static int
string_has_ctrl_or_space (const char *string)
@ -74,52 +115,66 @@ has_dotdot_after_at (const char *string)
}
/* Check whether the string has characters not valid in an RFC-822
address. To cope with OpenPGP we ignore non-ascii characters
so that for example umlauts are legal in an email address. An
OpenPGP user ID must be utf-8 encoded but there is no strict
requirement for RFC-822. Thus to avoid IDNA encoding we put the
address verbatim as utf-8 into the user ID under the assumption
that mail programs handle IDNA at a lower level and take OpenPGP
user IDs as utf-8. Note that we can't do an utf-8 encoding
checking here because in keygen.c this function is called with the
native encoding and native to utf-8 encoding is only done later. */
/* Check whether BUFFER has characters not valid in an RFC-822
address. LENGTH gives the length of BUFFER.
To cope with OpenPGP we ignore non-ascii characters so that for
example umlauts are legal in an email address. An OpenPGP user ID
must be utf-8 encoded but there is no strict requirement for
RFC-822. Thus to avoid IDNA encoding we put the address verbatim
as utf-8 into the user ID under the assumption that mail programs
handle IDNA at a lower level and take OpenPGP user IDs as utf-8.
Note that we can't do an utf-8 encoding checking here because in
keygen.c this function is called with the native encoding and
native to utf-8 encoding is only done later. */
int
has_invalid_email_chars (const char *s)
has_invalid_email_chars (const void *buffer, size_t length)
{
const unsigned char *s = buffer;
int at_seen=0;
const char *valid_chars=
"01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ( ; *s; s++ )
for ( ; length && *s; length--, s++ )
{
if ( (*s & 0x80) )
if ((*s & 0x80))
continue; /* We only care about ASCII. */
if ( *s == '@' )
if (*s == '@')
at_seen=1;
else if ( !at_seen && !(strchr (valid_chars, *s)
|| strchr ("!#$%&'*+/=?^`{|}~", *s)))
else if (!at_seen && !(strchr (valid_chars, *s)
|| strchr ("!#$%&'*+/=?^`{|}~", *s)))
return 1;
else if ( at_seen && !strchr( valid_chars, *s ) )
else if (at_seen && !strchr (valid_chars, *s))
return 1;
}
return 0;
}
/* Same as is_valid_mailbox (see below) but operates on non-nul
terminated buffer. */
int
is_valid_mailbox_mem (const void *name_arg, size_t namelen)
{
const char *name = name_arg;
return !( !name
|| !namelen
|| has_invalid_email_chars (name, namelen)
|| mem_count_chr (name, '@', namelen) != 1
|| *name == '@'
|| name[namelen-1] == '@'
|| name[namelen-1] == '.'
|| my_memstr (name, namelen, ".."));
}
/* Check whether NAME represents a valid mailbox according to
RFC822. Returns true if so. */
int
is_valid_mailbox (const char *name)
{
return !( !name
|| !*name
|| has_invalid_email_chars (name)
|| string_count_chr (name,'@') != 1
|| *name == '@'
|| name[strlen(name)-1] == '@'
|| name[strlen(name)-1] == '.'
|| strstr (name, "..") );
return name? is_valid_mailbox_mem (name, strlen (name)) : 0;
}

View File

@ -29,8 +29,9 @@
#ifndef GNUPG_COMMON_MBOX_UTIL_H
#define GNUPG_COMMON_MBOX_UTIL_H
int has_invalid_email_chars (const char *s);
int has_invalid_email_chars (const void *buffer, size_t length);
int is_valid_mailbox (const char *name);
int is_valid_mailbox_mem (const void *buffer, size_t length);
char *mailbox_from_userid (const char *userid);
int is_valid_user_id (const char *uid);