/* ** Copyright 2000 Double Precision, Inc. ** See COPYING for distribution information. */ /* ** $Id$ */ #include #include #include #include #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); }