/* * Copyright 1998-2002 Ben Smithurst * 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); }