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