else if (flags & (CH_NOQFROM) && ascii_strncasecmp (">From ", buf, 6) == 0) continue;
mutt_copy_hdr (FILE *in, FILE *out, long off_start, long 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;  int error;  if (ftell (in) != off_start)    fseek (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 (ftell (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 (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;	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 (ftell (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')    {      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;      /* 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));      /* Save the header in headers[x] */      if (!headers[x])	headers[x] = safe_strdup (buf);      else      {	safe_realloc ((void **) &headers[x],		      mutt_strlen (headers[x]) + mutt_strlen (buf) + sizeof (char));	strcat (headers[x], buf);	/* __STRCAT_CHECKED__ */      }    }  } /* while (ftell (in) < off_end) */  /* Now output the headers in order */  for (x = 0; x < hdr_count; x++)  {    if (headers[x])    {      if (flags & CH_DECODE)	rfc2047_decode (&headers[x]);      /* 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++)    safe_free ((void **) &headers[x]);  safe_free ((void **) &headers);  if (error)    return (-1);  return (0);}