/*
* Copyright 1998-2002 Ben Smithurst <ben@smithurst.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* strip Received: (and other) headers from mail folders to save space.
* used by ~/bin/rotatemail when archiving old mail.
*/
static const char rcsid[] =
"$BCPS: src/mailutils/mail-strip.c,v 1.42 2003/01/19 19:18:25 ben Exp $";
#include "misc.h"
void usage(void);
int strip_file(FILE *, FILE *);
int strip_maildir(int, char *, FILE *);
int
main(int argc, char *argv[]) {
if (getopt(argc, argv, "") != -1)
usage();
argv += optind;
argc -= optind;
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
return (process(argv, strip_file, strip_maildir) ? 0 : 1);
}
int
strip_maildir(int reset, char *fn, FILE *in_fp) {
FILE *out_fp;
char *outfn;
int e, ret;
if ((outfn = strdup(fn)) == NULL)
return (RET_ERROR);
assert (strncmp(fn, "new/", 4) == 0 || strncmp(fn, "cur/", 4) == 0);
memcpy(outfn, "tmp/", 4);
if ((out_fp = fopen(outfn, "w")) == NULL) {
e = errno;
free(outfn);
errno = e;
return (RET_ERROR);
}
ret = strip_file(in_fp, out_fp);
e = errno;
if (ret == RET_CHANGE) {
if (rename(outfn, fn) != 0) {
ret = RET_ERROR;
e = errno;
} else
ret = RET_NOCHANGE;
}
fclose(out_fp);
free(outfn);
errno = e;
return (ret);
}
int
strip_file(FILE *fp, FILE *out) {
int ignore, keep, header, retval, hdr_len;
size_t len;
char **pp, *line, *hdr_name;
/*
* headers to keep. MUST be lowercase and MUST be sorted.
*/
char *keeplist[] = {
"cc", "date", "from", "in-reply-to", "message-id",
"mime-version", "references", "reply-to", "sender", "status",
"subject", "to", "x-status", NULL
};
header = 1;
ignore = 0;
retval = RET_NOCHANGE;
hdr_name = NULL;
hdr_len = 0;
while ((line = gl_getline(fp)) != NULL) {
len = strlen(line);
if (sig_count > 0) {
warnx("strip_file: signal received, returning");
free(hdr_name);
return (RET_LOCALERROR);
}
chop(line, len);
if (is_from(line, 1)) {
header = 1;
ignore = 0;
fprintf(out, "%s\n", line);
continue;
}
/* check for end of headers */
if (*line == '\0') {
header = 0;
ignore = 0;
}
if (header && !isspace(*line)) {
/*
* it's a new header (i.e., not a long one which
* has been folded). get the header name and
* deal with it later.
*/
char *colon;
ignore = 0;
colon = strchr(line, ':');
if (colon == NULL) {
/*
* probably not really headers. Originally,
* this would cause the program to abort,
* but some mailboxes do have lines
* starting with From_ which aren't the
* start of a new message.
*/
header = 0;
fprintf(out, "%s\n", line);
continue;
} else {
int i;
/*
* If the already allocated space isn't
* large enough, free it and allocate
* space which is large enough.
*/
i = colon - line + 1;
if (i > hdr_len) {
free(hdr_name);
hdr_name = malloc(i);
if (hdr_name == NULL)
return (RET_ERROR);
hdr_len = i;
}
/* Do the actual copy. */
i = 0;
while (line + i < colon) {
hdr_name[i] = tolower(line[i]);
i++;
}
hdr_name[i] = '\0';
}
} else {
/*
* it's either a subsequent line of a multiline
* header or it's in the body. print it,
* unless it's part of a header we're ignoring.
* (ignore === 0 in the body).
*/
if (!ignore)
fprintf(out, "%s\n", line);
continue;
}
/* check if it's a header we want to keep */
keep = strncmp(hdr_name, "content-", 8) == 0;
keep = keep || (strncmp(hdr_name, "x-spam-", 7) == 0);
if (!keep) {
int diff;
for (pp = keeplist; *pp != NULL; pp++) {
diff = strcmp(hdr_name, *pp);
if (diff == 0) {
/* header found in keeplist */
keep = 1;
break;
} else if (diff < 0)
/*
* header from list is greater
* than the header we're checking,
* so this header isn't in the list.
*/
break;
}
}
if (keep)
fprintf(out, "%s\n", line);
else {
ignore = 1;
retval = RET_CHANGE;
}
}
gl_destroy(fp);
free(hdr_name);
return (retval);
}
void
usage(void) {
fprintf(stderr, "usage: mail-strip [file ...]\n");
exit(EX_USAGE);
}
syntax highlighted by Code2HTML, v. 0.9.1