255 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  | ** Copyright 2000 Double Precision, Inc. | ||
|  | ** See COPYING for distribution information. | ||
|  | */ | ||
|  | 
 | ||
|  | /*
 | ||
|  | ** $Id$ | ||
|  | */ | ||
|  | #include	<stdio.h>
 | ||
|  | #include	<ctype.h>
 | ||
|  | #include	<stdlib.h>
 | ||
|  | #include	<string.h>
 | ||
|  | #include	"rfc822.h"
 | ||
|  | #ifndef __WINDOWS__
 | ||
|  | #include	"config.h"
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if	HAVE_STRCASECMP
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | #define	strcasecmp	stricmp
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if	HAVE_STRNCASECMP
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | #define	strncasecmp	strnicmp
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /* Remove artifacts from the subject header */ | ||
|  | 
 | ||
|  | static void stripsubj(char *s, int *hasrefwd) | ||
|  | { | ||
|  | 	char	*p; | ||
|  | 	char	*q; | ||
|  | 
 | ||
|  | 	for (p=q=s; *p; p++) | ||
|  | 	{ | ||
|  | 		if (!isspace((int)(unsigned char)*p)) | ||
|  | 		{ | ||
|  | 			*q++=*p; | ||
|  | 			continue; | ||
|  | 		} | ||
|  | 		while (p[1] && isspace((int)(unsigned char)p[1])) | ||
|  | 		{ | ||
|  | 			++p; | ||
|  | 		} | ||
|  | 		*q++=' '; | ||
|  | 	} | ||
|  | 	*q=0; | ||
|  | 
 | ||
|  | 	for (;;) | ||
|  | 	{ | ||
|  | 		/*
 | ||
|  | 		** | ||
|  | 		** (2) Remove all trailing text of the subject that matches | ||
|  | 		** the subj-trailer ABNF, repeat until no more matches are | ||
|  | 		** possible. | ||
|  | 		** | ||
|  | 		**  subj-trailer    = "(fwd)" / WSP | ||
|  | 		*/ | ||
|  | 
 | ||
|  | 		for (p=s; *p; p++) | ||
|  | 			; | ||
|  | 		while (p > s) | ||
|  | 		{ | ||
|  | 			if ( isspace((int)(unsigned char)p[-1])) | ||
|  | 			{ | ||
|  | 				--p; | ||
|  | 				continue; | ||
|  | 			} | ||
|  | 			if (p-s >= 5 && strncasecmp(p-5, "(FWD)", 5) == 0) | ||
|  | 			{ | ||
|  | 				p -= 5; | ||
|  | 				*hasrefwd=1; | ||
|  | 				continue; | ||
|  | 			} | ||
|  | 			break; | ||
|  | 		} | ||
|  | 		*p=0; | ||
|  | 
 | ||
|  | 		for (p=s; *p; ) | ||
|  | 		{ | ||
|  | 			int isrefwd=0; | ||
|  | 
 | ||
|  | 			for (;;) | ||
|  | 			{ | ||
|  | 				int needcolon=1; | ||
|  | 
 | ||
|  | 				/*
 | ||
|  | 				** | ||
|  | 				** (3) Remove all prefix text of the subject | ||
|  | 				** that matches the subj-leader ABNF. | ||
|  | 				** | ||
|  | 				**   subj-leader     = (*subj-blob subj-refwd) / WSP | ||
|  | 				** | ||
|  | 				**   subj-blob       = "[" *BLOBCHAR "]" *WSP | ||
|  | 				** | ||
|  | 				**   subj-refwd      = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" | ||
|  | 				** | ||
|  | 				**   BLOBCHAR        = %x01-5a / %x5c / %x5e-7f | ||
|  | 				**                   ; any CHAR except '[' and ']' | ||
|  | 				** | ||
|  | 				**   THIS IS A BUG: whitespace should also be excluded from BLOBCHAR | ||
|  | 				*/ | ||
|  | 
 | ||
|  | 				if (isspace((int)(unsigned char)*p)) | ||
|  | 				{ | ||
|  | 					++p; | ||
|  | 					continue; | ||
|  | 				} | ||
|  | 				if (strncasecmp(p, "RE", 2) == 0) | ||
|  | 				{ | ||
|  | 					q=p+2; | ||
|  | 					isrefwd=1; | ||
|  | 				} | ||
|  | 				else if (strncasecmp(p, "FWD", 3) == 0) | ||
|  | 				{ | ||
|  | 					q=p+3; | ||
|  | 					isrefwd=1; | ||
|  | 				} | ||
|  | 				else if (strncasecmp(p, "FW", 2) == 0) | ||
|  | 				{ | ||
|  | 					q=p+2; | ||
|  | 					isrefwd=1; | ||
|  | 				} | ||
|  | 				else if (*p == '[') | ||
|  | 				{ | ||
|  | 					q=p; | ||
|  | 					needcolon=0; | ||
|  | 				} | ||
|  | 				else | ||
|  | 					break; | ||
|  | 
 | ||
|  | 				if (*q == '[') | ||
|  | 				{ | ||
|  | 					++q; | ||
|  | 
 | ||
|  | 					while (*q && *q != '[' && *q != ']' | ||
|  | 					       && *q != ' ') | ||
|  | 						++q; | ||
|  | 
 | ||
|  | 					if (*q != ']')	break; | ||
|  | 					++q; | ||
|  | 				} | ||
|  | 				if (needcolon && *q++ != ':')	break; | ||
|  | 				p=q; | ||
|  | 			} | ||
|  | 			/*
 | ||
|  | 			** (4) If there is prefix text of the subject that | ||
|  | 			** matches the subj-blob ABNF, and removing that | ||
|  | 			** prefix leaves a non-empty subj-base, then remove | ||
|  | 			** the prefix text. | ||
|  | 			** | ||
|  | 			**   subj-base       = NONWSP *([*WSP] NONWSP) | ||
|  | 			**                   ; can be a subj-blob | ||
|  | 			*/ | ||
|  | 
 | ||
|  | 
 | ||
|  | 			if (*p == '[') | ||
|  | 			{ | ||
|  | 				for (q=p; *q; q++) | ||
|  | 					if (*q == '[' || *q == ' ' | ||
|  | 					    || *q == ']') | ||
|  | 						break; | ||
|  | 				if (*q == ']') | ||
|  | 				{ | ||
|  | 					++q; | ||
|  | 					while (*q && isspace((int)(unsigned | ||
|  | 								   char)*q)) | ||
|  | 						++q; | ||
|  | 
 | ||
|  | 					if (*q) | ||
|  | 					{ | ||
|  | 						p=q; | ||
|  | 						if (isrefwd) | ||
|  | 							*hasrefwd=1; | ||
|  | 						continue; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			if (isrefwd) | ||
|  | 				*hasrefwd=1; | ||
|  | 
 | ||
|  | 			break; | ||
|  | 		} | ||
|  | 		/*
 | ||
|  | 		** | ||
|  | 		** (6) If the resulting text begins with the subj-fwd-hdr ABNF | ||
|  | 		** and ends with the subj-fwd-trl ABNF, remove the | ||
|  | 		** subj-fwd-hdr and subj-fwd-trl and repeat from step (2). | ||
|  | 		** | ||
|  | 		**   subj-fwd-hdr    = "[fwd:" | ||
|  | 		** | ||
|  | 		**   subj-fwd-trl    = "]" | ||
|  | 		*/ | ||
|  | 
 | ||
|  | 		if (strncasecmp(p, "[FWD:", 5) == 0) | ||
|  | 		{ | ||
|  | 			q=strrchr(p, ']'); | ||
|  | 			if (q && q[1] == 0) | ||
|  | 			{ | ||
|  | 				*q=0; | ||
|  | 				p += 5; | ||
|  | 
 | ||
|  | 				q=s; | ||
|  | 				while ( (*q++ = *p++) != 0) | ||
|  | 					; | ||
|  | 
 | ||
|  | 				*hasrefwd=1; | ||
|  | 				continue; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		break; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	q=s; | ||
|  | 	while ( (*q++ = *p++) != 0) | ||
|  | 		; | ||
|  | } | ||
|  | 
 | ||
|  | char *rfc822_coresubj(const char *s, int *hasrefwd) | ||
|  | { | ||
|  | 	char *q=strdup(s), *r; | ||
|  | 	int dummy; | ||
|  | 
 | ||
|  | 	if (!hasrefwd) | ||
|  | 		hasrefwd= &dummy; | ||
|  | 
 | ||
|  | 	*hasrefwd=0; | ||
|  | 	if (!q)	return (0); | ||
|  | 
 | ||
|  | 	for (r=q; *r; r++) | ||
|  | 		if ((*r & 0x80) == 0)	/* Just US-ASCII casing, thanks */ | ||
|  | 			*r=toupper((int)(unsigned char)*r); | ||
|  | 	stripsubj(q, hasrefwd); | ||
|  | 	return (q); | ||
|  | } | ||
|  | 
 | ||
|  | char *rfc822_coresubj_nouc(const char *s, int *hasrefwd) | ||
|  | { | ||
|  | 	char *q=strdup(s); | ||
|  | 	int dummy; | ||
|  | 
 | ||
|  | 	if (!hasrefwd) | ||
|  | 		hasrefwd= &dummy; | ||
|  | 
 | ||
|  | 	*hasrefwd=0; | ||
|  | 	if (!q)	return (0); | ||
|  | 
 | ||
|  | 	stripsubj(q, hasrefwd); | ||
|  | 	return (q); | ||
|  | } |