diff options
Diffstat (limited to 'src/global/is_header.c')
-rw-r--r-- | src/global/is_header.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/global/is_header.c b/src/global/is_header.c new file mode 100644 index 0000000..891e137 --- /dev/null +++ b/src/global/is_header.c @@ -0,0 +1,92 @@ +/*++ +/* NAME +/* is_header 3 +/* SUMMARY +/* message header classification +/* SYNOPSIS +/* #include <is_header.h> +/* +/* ssize_t is_header(string) +/* const char *string; +/* +/* ssize_t is_header_buf(string, len) +/* const char *string; +/* ssize_t len; +/* DESCRIPTION +/* is_header() examines the given string and returns non-zero (true) +/* when it begins with a mail header name + optional space + colon. +/* The result is the length of the mail header name. +/* +/* is_header_buf() is a more elaborate interface for use with strings +/* that may not be null terminated. +/* STANDARDS +/* RFC 822 (ARPA Internet Text Messages) +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include "sys_defs.h" +#include <ctype.h> + +/* Global library. */ + +#include "is_header.h" + +/* is_header_buf - determine if this can be a header line */ + +ssize_t is_header_buf(const char *str, ssize_t str_len) +{ + const unsigned char *cp; + int state; + int c; + ssize_t len; + +#define INIT 0 +#define IN_CHAR 1 +#define IN_CHAR_SPACE 2 +#define CU_CHAR_PTR(x) ((const unsigned char *) (x)) + + /* + * XXX RFC 2822 Section 4.5, Obsolete header fields: whitespace may + * appear between header label and ":" (see: RFC 822, Section 3.4.2.). + * + * XXX Don't run off the end in case some non-standard iscntrl() + * implementation considers null a non-control character... + */ + for (len = 0, state = INIT, cp = CU_CHAR_PTR(str); /* see below */; cp++) { + if (str_len != IS_HEADER_NULL_TERMINATED && str_len-- <= 0) + return (0); + switch (c = *cp) { + default: + if (c == 0 || !ISASCII(c) || ISCNTRL(c)) + return (0); + if (state == INIT) + state = IN_CHAR; + if (state == IN_CHAR) { + len++; + continue; + } + return (0); + case ' ': + case '\t': + if (state == IN_CHAR) + state = IN_CHAR_SPACE; + if (state == IN_CHAR_SPACE) + continue; + return (0); + case ':': + return ((state == IN_CHAR || state == IN_CHAR_SPACE) ? len : 0); + } + } + /* Redundant return for future proofing. */ + return (0); +} |