📄 copy.c
字号:
/* * Copyright (C) 1996-2000,2002 Michael R. Elkins <me@mutt.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mailbox.h"#include "mx.h"#include "copy.h"#include "rfc2047.h"#include "mime.h"#include "mutt_crypt.h"#include "mutt_idna.h"#include <string.h>#include <stdlib.h>#include <ctype.h>#include <unistd.h> /* needed for SEEK_SET under SunOS 4.1.4 */static int address_header_decode (char **str);static int copy_delete_attach (BODY *b, FILE *fpin, FILE *fpout, char *date);/* Ok, the only reason for not merging this with mutt_copy_header() * below is to avoid creating a HEADER structure in message_handler(). */intmutt_copy_hdr (FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end, int flags, const char *prefix){ int from = 0; int this_is_from; int ignore = 0; char buf[STRING]; /* should be long enough to get most fields in one pass */ char *nl; LIST *t; char **headers; int hdr_count; int x; char *this_one = NULL; int error; if (ftello (in) != off_start) fseeko (in, off_start, 0); buf[0] = '\n'; buf[1] = 0; if ((flags & (CH_REORDER | CH_WEED | CH_MIME | CH_DECODE | CH_PREFIX | CH_WEED_DELIVERED)) == 0) { /* Without these flags to complicate things * we can do a more efficient line to line copying */ while (ftello (in) < off_end) { nl = strchr (buf, '\n'); if ((fgets (buf, sizeof (buf), in)) == NULL) break; /* Is it the begining of a header? */ if (nl && buf[0] != ' ' && buf[0] != '\t') { ignore = 1; if (!from && mutt_strncmp ("From ", buf, 5) == 0) { if ((flags & CH_FROM) == 0) continue; from = 1; } else if (flags & (CH_NOQFROM) && ascii_strncasecmp (">From ", buf, 6) == 0) continue; else if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) break; /* end of header */ if ((flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) && (ascii_strncasecmp ("Status:", buf, 7) == 0 || ascii_strncasecmp ("X-Status:", buf, 9) == 0)) continue; if ((flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) && (ascii_strncasecmp ("Content-Length:", buf, 15) == 0 || ascii_strncasecmp ("Lines:", buf, 6) == 0)) continue; if ((flags & CH_UPDATE_REFS) && ascii_strncasecmp ("References:", buf, 11) == 0) continue; if ((flags & CH_UPDATE_IRT) && ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) continue; ignore = 0; } if (!ignore && fputs (buf, out) == EOF) return (-1); } return 0; } hdr_count = 1; x = 0; error = FALSE; /* We are going to read and collect the headers in an array * so we are able to do re-ordering. * First count the number of entries in the array */ if (flags & CH_REORDER) { for (t = HeaderOrderList; t; t = t->next) { dprint(1, (debugfile, "Reorder list: %s\n", t->data)); hdr_count++; } } dprint (1, (debugfile, "WEED is %s\n", (flags & CH_WEED) ? "Set" : "Not")); headers = safe_calloc (hdr_count, sizeof (char *)); /* Read all the headers into the array */ while (ftello (in) < off_end) { nl = strchr (buf, '\n'); /* Read a line */ if ((fgets (buf, sizeof (buf), in)) == NULL) break; /* Is it the begining of a header? */ if (nl && buf[0] != ' ' && buf[0] != '\t') { /* Do we have anything pending? */ if (this_one) { if (flags & CH_DECODE) { if (!address_header_decode (&this_one)) rfc2047_decode (&this_one); } if (!headers[x]) headers[x] = this_one; else { safe_realloc (&headers[x], mutt_strlen (headers[x]) + mutt_strlen (this_one) + sizeof (char)); strcat (headers[x], this_one); /* __STRCAT_CHECKED__ */ FREE (&this_one); } this_one = NULL; } ignore = 1; this_is_from = 0; if (!from && mutt_strncmp ("From ", buf, 5) == 0) { if ((flags & CH_FROM) == 0) continue; this_is_from = from = 1; } else if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) break; /* end of header */ /* note: CH_FROM takes precedence over header weeding. */ if (!((flags & CH_FROM) && (flags & CH_FORCE_FROM) && this_is_from) && (flags & CH_WEED) && mutt_matches_ignore (buf, Ignore) && !mutt_matches_ignore (buf, UnIgnore)) continue; if ((flags & CH_WEED_DELIVERED) && ascii_strncasecmp ("Delivered-To:", buf, 13) == 0) continue; if ((flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) && (ascii_strncasecmp ("Status:", buf, 7) == 0 || ascii_strncasecmp ("X-Status:", buf, 9) == 0)) continue; if ((flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) && (ascii_strncasecmp ("Content-Length:", buf, 15) == 0 || ascii_strncasecmp ("Lines:", buf, 6) == 0)) continue; if ((flags & CH_MIME) && ((ascii_strncasecmp ("content-", buf, 8) == 0 && (ascii_strncasecmp ("transfer-encoding:", buf + 8, 18) == 0 || ascii_strncasecmp ("type:", buf + 8, 5) == 0)) || ascii_strncasecmp ("mime-version:", buf, 13) == 0)) continue; if ((flags & CH_UPDATE_REFS) && ascii_strncasecmp ("References:", buf, 11) == 0) continue; if ((flags & CH_UPDATE_IRT) && ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) continue; /* Find x -- the array entry where this header is to be saved */ if (flags & CH_REORDER) { for (t = HeaderOrderList, x = 0 ; (t) ; t = t->next, x++) { if (!ascii_strncasecmp (buf, t->data, mutt_strlen (t->data))) { dprint(2, (debugfile, "Reorder: %s matches %s\n", t->data, buf)); break; } } } ignore = 0; } /* If beginning of header */ if (!ignore) { dprint (2, (debugfile, "Reorder: x = %d; hdr_count = %d\n", x, hdr_count)); if (!this_one) this_one = safe_strdup (buf); else { safe_realloc (&this_one, mutt_strlen (this_one) + mutt_strlen (buf) + sizeof (char)); strcat (this_one, buf); /* __STRCAT_CHECKED__ */ } } } /* while (ftello (in) < off_end) */ /* Do we have anything pending? -- XXX, same code as in above in the loop. */ if (this_one) { if (flags & CH_DECODE) { if (!address_header_decode (&this_one)) rfc2047_decode (&this_one); } if (!headers[x]) headers[x] = this_one; else { safe_realloc (&headers[x], mutt_strlen (headers[x]) + mutt_strlen (this_one) + sizeof (char)); strcat (headers[x], this_one); /* __STRCAT_CHECKED__ */ FREE (&this_one); } this_one = NULL; } /* Now output the headers in order */ for (x = 0; x < hdr_count; x++) { if (headers[x]) {#if 0 if (flags & CH_DECODE) rfc2047_decode (&headers[x]);#endif /* We couldn't do the prefixing when reading because RFC 2047 * decoding may have concatenated lines. */ if (flags & CH_PREFIX) { char *ch = headers[x]; int print_prefix = 1; while (*ch) { if (print_prefix) { if (fputs (prefix, out) == EOF) { error = TRUE; break; } print_prefix = 0; } if (*ch == '\n' && ch[1]) print_prefix = 1; if (putc (*ch++, out) == EOF) { error = TRUE; break; } } if (error) break; } else { if (fputs (headers[x], out) == EOF) { error = TRUE; break; } } } } /* Free in a separate loop to be sure that all headers are freed * in case of error. */ for (x = 0; x < hdr_count; x++) FREE (&headers[x]); FREE (&headers); if (error) return (-1); return (0);}/* flags CH_DECODE RFC2047 header decoding CH_FROM retain the "From " message separator CH_FORCE_FROM give CH_FROM precedence over CH_WEED CH_MIME ignore MIME fields CH_NOLEN don't write Content-Length: and Lines: CH_NONEWLINE don't output a newline after the header CH_NOSTATUS ignore the Status: and X-Status: CH_PREFIX quote header with $indent_str CH_REORDER output header in order specified by `hdr_order' CH_TXTPLAIN generate text/plain MIME headers [hack alert.] CH_UPDATE write new Status: and X-Status: CH_UPDATE_LEN write new Content-Length: and Lines: CH_XMIT ignore Lines: and Content-Length: CH_WEED do header weeding CH_NOQFROM ignore ">From " line CH_UPDATE_IRT update the In-Reply-To: header CH_UPDATE_REFS update the References: header prefix string to use if CH_PREFIX is set */intmutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix){ char buffer[SHORT_STRING]; if (h->env) flags |= (h->env->irt_changed ? CH_UPDATE_IRT : 0) | (h->env->refs_changed ? CH_UPDATE_REFS : 0); if (mutt_copy_hdr (in, out, h->offset, h->content->offset, flags, prefix) == -1) return (-1); if (flags & CH_TXTPLAIN) { char chsbuf[SHORT_STRING]; fputs ("MIME-Version: 1.0\n", out); fputs ("Content-Transfer-Encoding: 8bit\n", out); fputs ("Content-Type: text/plain; charset=", out); mutt_canonical_charset (chsbuf, sizeof (chsbuf), Charset ? Charset : "us-ascii"); rfc822_cat(buffer, sizeof(buffer), chsbuf, MimeSpecials); fputs(buffer, out); fputc('\n', out); if (ferror (out) != 0 || feof (out) != 0) return -1; } if (flags & CH_UPDATE) { if ((flags & CH_NOSTATUS) == 0) { if (h->env->irt_changed && h->env->in_reply_to) { LIST *listp = h->env->in_reply_to; if (fputs ("In-Reply-To: ", out) == EOF) return (-1); for (; listp; listp = listp->next) if ((fputs (listp->data, out) == EOF) || (fputc (' ', out) == EOF)) return (-1); if (fputc ('\n', out) == EOF) return (-1); } if (h->env->refs_changed && h->env->references) { LIST *listp = h->env->references, *refs = NULL, *t; if (fputs ("References: ", out) == EOF) return (-1); /* Mutt stores references in reverse order, thus we create * a reordered refs list that we can put in the headers */ for (; listp; listp = listp->next, refs = t) { t = (LIST *)safe_malloc (sizeof (LIST)); t->data = listp->data; t->next = refs; } for (; refs; refs = refs->next) if ((fputs (refs->data, out) == EOF) || (fputc (' ', out) == EOF)) return (-1); /* clearing refs from memory */ for (t = refs; refs; refs = t->next, t = refs) FREE (&refs); if (fputc ('\n', out) == EOF) return (-1); } if (h->old || h->read) { if (fputs ("Status: ", out) == EOF) return (-1); if (h->read) { if (fputs ("RO", out) == EOF) return (-1); } else if (h->old) { if (fputc ('O', out) == EOF) return (-1); } if (fputc ('\n', out) == EOF) return (-1); } if (h->flagged || h->replied) { if (fputs ("X-Status: ", out) == EOF) return (-1); if (h->replied) { if (fputc ('A', out) == EOF) return (-1); } if (h->flagged) { if (fputc ('F', out) == EOF) return (-1); } if (fputc ('\n', out) == EOF) return (-1); } } } if (flags & CH_UPDATE_LEN && (flags & CH_NOLEN) == 0) { fprintf (out, "Content-Length: " OFF_T_FMT "\n", h->content->length); if (h->lines != 0 || h->content->length == 0) fprintf (out, "Lines: %d\n", h->lines); } if ((flags & CH_NONEWLINE) == 0) { if (flags & CH_PREFIX) fputs(prefix, out); if (fputc ('\n', out) == EOF) /* add header terminator */ return (-1); } if (ferror (out) || feof (out)) return -1; return (0);}/* Count the number of lines and bytes to be deleted in this body*/static int count_delete_lines (FILE *fp, BODY *b, LOFF_T *length, size_t datelen){ int dellines = 0; long l; int ch; if (b->deleted) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -