diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /rfc822/imapsubj.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'rfc822/imapsubj.c')
| -rw-r--r-- | rfc822/imapsubj.c | 305 | 
1 files changed, 305 insertions, 0 deletions
| diff --git a/rfc822/imapsubj.c b/rfc822/imapsubj.c new file mode 100644 index 0000000..2f6adfd --- /dev/null +++ b/rfc822/imapsubj.c @@ -0,0 +1,305 @@ +/* +** Copyright 2000 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +/* +*/ +#include	"config.h" +#include	<stdio.h> +#include	<ctype.h> +#include	<stdlib.h> +#include	<string.h> +#include	"rfc822.h" + +#if	HAVE_STRCASECMP + +#else +#define	strcasecmp	stricmp +#endif + +#if	HAVE_STRNCASECMP + +#else +#define	strncasecmp	strnicmp +#endif + +/* Skip over blobs */ + +static char *skipblob(char *p, char **save_blob_ptr) +{ +	char *q; +	char *orig_p=p; +	int isalldigits=1; + +	if (*p == '[') +	{ +		for (q= p+1; *q; q++) +			if (*q == '[' || *q == ']') +				break; +			else if (strchr("0123456789", *q) == NULL) +				isalldigits=0; + +		if (*q == ']') +		{ +			p=q+1; + +			while (isspace((int)(unsigned char)*p)) +			{ +				++p; +			} + +			if (save_blob_ptr && *save_blob_ptr && !isalldigits) +			{ +				while (orig_p != p) +					*(*save_blob_ptr)++=*orig_p++; +			} + +			return (p); +		} +	} +	return (p); +} + +static char *skipblobs(char *p, char **save_blob_ptr) +{ +	char *q=p; + +	do +	{ +		p=q; +		q=skipblob(p, save_blob_ptr); +	} while (q != p); +	return (q); +} + +/* Remove artifacts from the subject header */ + +static void stripsubj(char *s, int *hasrefwd, char *save_blob_buf) +{ +	char	*p; +	char	*q; +	int doit; + +	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; + +	do +	{ +		doit=0; +		/* +		** +		** (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 |= CORESUBJ_FWD; +				continue; +			} +			break; +		} +		*p=0; + +		for (p=s; *p; ) +		{ +			for (;;) +			{ +				char *orig_blob_ptr; +				int flag=CORESUBJ_FWD; + +				/* +				** +				** (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 ']' +				*/ + +				if (isspace((int)(unsigned char)*p)) +				{ +					++p; +					continue; +				} + +				q=skipblobs(p, NULL); + +				if (strncasecmp(q, "RE", 2) == 0) +				{ +					flag=CORESUBJ_RE; +					q += 2; +				} +				else if (strncasecmp(q, "FWD", 3) == 0) +				{ +					q += 3; +				} +				else if (strncasecmp(q, "FW", 2) == 0) +				{ +					q += 2; +				} +				else q=0; + +				if (q) +				{ +					orig_blob_ptr=save_blob_buf; + +					q=skipblob(q, &save_blob_buf); +					if (*q == ':') +					{ +						p=q+1; +						*hasrefwd |= flag; +						continue; +					} + +					save_blob_buf=orig_blob_ptr; +				} + + +				/* +				** (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 +				*/ + +				orig_blob_ptr=save_blob_buf; + +				q=skipblob(p, &save_blob_buf); + +				if (q != p && *q) +				{ +					p=q; +					continue; +				} +				save_blob_buf=orig_blob_ptr; +				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; +					*hasrefwd |= CORESUBJ_FWD; + +					for (q=s; (*q++=*p++) != 0; ) +						; +					doit=1; +				} +			} +			break; +		} +	} while (doit); + +	q=s; +	while ( (*q++ = *p++) != 0) +		; +	if (save_blob_buf) +		*save_blob_buf=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 */ +		{ +			if (*r >= 'a' && *r <= 'z') +				*r += 'A'-'a'; +		} +	stripsubj(q, hasrefwd, 0); +	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, 0); +	return (q); +} + +char *rfc822_coresubj_keepblobs(const char *s) +{ +	char *q=strdup(s), *r; +	int dummy; + +	if (!q)	return (0); + +	r=strdup(s); +	if (!r) +	{ +		free(q); +		return (0); +	} + +	stripsubj(q, &dummy, r); +	strcat(r, q); +	free(q); +	return (r); +} | 
