1/*++ 2/* NAME 3/* is_header 3 4/* SUMMARY 5/* message header classification 6/* SYNOPSIS 7/* #include <is_header.h> 8/* 9/* ssize_t is_header(string) 10/* const char *string; 11/* 12/* ssize_t is_header_buf(string, len) 13/* const char *string; 14/* ssize_t len; 15/* DESCRIPTION 16/* is_header() examines the given string and returns non-zero (true) 17/* when it begins with a mail header name + optional space + colon. 18/* The result is the length of the mail header name. 19/* 20/* is_header_buf() is a more elaborate interface for use with strings 21/* that may not be null terminated. 22/* STANDARDS 23/* RFC 822 (ARPA Internet Text Messages) 24/* LICENSE 25/* .ad 26/* .fi 27/* The Secure Mailer license must be distributed with this software. 28/* AUTHOR(S) 29/* Wietse Venema 30/* IBM T.J. Watson Research 31/* P.O. Box 704 32/* Yorktown Heights, NY 10598, USA 33/*--*/ 34 35/* System library. */ 36 37#include "sys_defs.h" 38#include <ctype.h> 39 40/* Global library. */ 41 42#include "is_header.h" 43 44/* is_header_buf - determine if this can be a header line */ 45 46ssize_t is_header_buf(const char *str, ssize_t str_len) 47{ 48 const unsigned char *cp; 49 int state; 50 int c; 51 ssize_t len; 52 53#define INIT 0 54#define IN_CHAR 1 55#define IN_CHAR_SPACE 2 56#define CU_CHAR_PTR(x) ((const unsigned char *) (x)) 57 58 /* 59 * XXX RFC 2822 Section 4.5, Obsolete header fields: whitespace may 60 * appear between header label and ":" (see: RFC 822, Section 3.4.2.). 61 * 62 * XXX Don't run off the end in case some non-standard iscntrl() 63 * implementation considers null a non-control character... 64 */ 65 for (len = 0, state = INIT, cp = CU_CHAR_PTR(str); /* see below */; cp++) { 66 if (str_len != IS_HEADER_NULL_TERMINATED && str_len-- <= 0) 67 return (0); 68 switch (c = *cp) { 69 default: 70 if (c == 0 || !ISASCII(c) || ISCNTRL(c)) 71 return (0); 72 if (state == INIT) 73 state = IN_CHAR; 74 if (state == IN_CHAR) { 75 len++; 76 continue; 77 } 78 return (0); 79 case ' ': 80 case '\t': 81 if (state == IN_CHAR) 82 state = IN_CHAR_SPACE; 83 if (state == IN_CHAR_SPACE) 84 continue; 85 return (0); 86 case ':': 87 return ((state == IN_CHAR || state == IN_CHAR_SPACE) ? len : 0); 88 } 89 } 90 /* Redundant return for future proofing. */ 91 return (0); 92} 93