⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sendlib.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 1996-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. */ #define _SENDLIB_C 1#if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_curses.h"#include "rfc2047.h"#include "rfc2231.h"#include "mx.h"#include "mime.h"#include "mailbox.h"#include "copy.h"#include "pager.h"#include "charset.h"#include "mutt_crypt.h"#include "mutt_idna.h"#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <ctype.h>#include <sys/stat.h>#include <signal.h>#include <sys/wait.h>#include <fcntl.h>#ifdef HAVE_SYSEXITS_H#include <sysexits.h>#else /* Make sure EX_OK is defined <philiph@pobox.com> */#define EX_OK 0#endif/* If you are debugging this file, comment out the following line. *//*#define NDEBUG*/#ifdef NDEBUG#define assert(x)#else#include <assert.h>#endifextern char RFC822Specials[];#define DISPOSITION(X) X==DISPATTACH?"attachment":"inline"const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t";char B64Chars[64] = {  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',  't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9', '+', '/'};static char MsgIdPfx = 'A';static void transform_to_7bit (BODY *a, FILE *fpin);static void encode_quoted (FGETCONV * fc, FILE *fout, int istext){  int c, linelen = 0;  char line[77], savechar;  while ((c = fgetconv (fc)) != EOF)  {    /* Wrap the line if needed. */    if (linelen == 76 && ((istext && c != '\n') || !istext))    {      /* If the last character is "quoted", then be sure to move all three       * characters to the next line.  Otherwise, just move the last       * character...       */      if (line[linelen-3] == '=')      {        line[linelen-3] = 0;        fputs (line, fout);              fputs ("=\n", fout);        line[linelen] = 0;        line[0] = '=';        line[1] = line[linelen-2];        line[2] = line[linelen-1];        linelen = 3;      }      else      {        savechar = line[linelen-1];        line[linelen-1] = '=';        line[linelen] = 0;        fputs (line, fout);        fputc ('\n', fout);        line[0] = savechar;        linelen = 1;      }    }    /* Escape lines that begin with/only contain "the message separator". */    if (linelen == 4 && !mutt_strncmp ("From", line, 4))    {      strfcpy (line, "=46rom", sizeof (line));      linelen = 6;    }    else if (linelen == 4 && !mutt_strncmp ("from", line, 4))    {      strfcpy (line, "=66rom", sizeof (line));      linelen = 6;    }    else if (linelen == 1 && line[0] == '.')    {      strfcpy (line, "=2E", sizeof (line));      linelen = 3;    }    if (c == '\n' && istext)    {      /* Check to make sure there is no trailing space on this line. */      if (linelen > 0 && (line[linelen-1] == ' ' || line[linelen-1] == '\t'))      {        if (linelen < 74)	{          sprintf (line+linelen-1, "=%2.2X", (unsigned char) line[linelen-1]);          fputs (line, fout);        }        else	{          int savechar = line[linelen-1];          line[linelen-1] = '=';          line[linelen] = 0;          fputs (line, fout);          fprintf (fout, "\n=%2.2X", (unsigned char) savechar);        }      }      else      {        line[linelen] = 0;        fputs (line, fout);      }      fputc ('\n', fout);      linelen = 0;    }    else if (c != 9 && (c < 32 || c > 126 || c == '='))    {      /* Check to make sure there is enough room for the quoted character.       * If not, wrap to the next line.       */      if (linelen > 73)      {        line[linelen++] = '=';        line[linelen] = 0;        fputs (line, fout);        fputc ('\n', fout);        linelen = 0;      }      sprintf (line+linelen,"=%2.2X", (unsigned char) c);      linelen += 3;    }    else    {      /* Don't worry about wrapping the line here.  That will happen during       * the next iteration when I'll also know what the next character is.       */      line[linelen++] = c;    }  }  /* Take care of anything left in the buffer */  if (linelen > 0)  {    if (line[linelen-1] == ' ' || line[linelen-1] == '\t')    {      /* take care of trailing whitespace */      if (linelen < 74)        sprintf (line+linelen-1, "=%2.2X", (unsigned char) line[linelen-1]);      else      {        savechar = line[linelen-1];        line[linelen-1] = '=';        line[linelen] = 0;        fputs (line, fout);        fputc ('\n', fout);        sprintf (line, "=%2.2X", (unsigned char) savechar);      }    }    else      line[linelen] = 0;    fputs (line, fout);  }}static char b64_buffer[3];static short b64_num;static short b64_linelen;static void b64_flush(FILE *fout){  short i;  if(!b64_num)    return;  if(b64_linelen >= 72)  {    fputc('\n', fout);    b64_linelen = 0;  }    for(i = b64_num; i < 3; i++)    b64_buffer[i] = '\0';    fputc(B64Chars[(b64_buffer[0] >> 2) & 0x3f], fout);   b64_linelen++;  fputc(B64Chars[((b64_buffer[0] & 0x3) << 4) | ((b64_buffer[1] >> 4) & 0xf) ], fout);  b64_linelen++;    if(b64_num > 1)  {    fputc(B64Chars[((b64_buffer[1] & 0xf) << 2) | ((b64_buffer[2] >> 6) & 0x3) ], fout);    b64_linelen++;    if(b64_num > 2)    {      fputc(B64Chars[b64_buffer[2] & 0x3f], fout);      b64_linelen++;    }  }    while(b64_linelen % 4)  {    fputc('=', fout);    b64_linelen++;  }    b64_num = 0;}      static void b64_putc(char c, FILE *fout){  if(b64_num == 3)    b64_flush(fout);    b64_buffer[b64_num++] = c;}    static void encode_base64 (FGETCONV * fc, FILE *fout, int istext){  int ch, ch1 = EOF;    b64_num = b64_linelen = 0;    while ((ch = fgetconv (fc)) != EOF)  {    if (istext && ch == '\n' && ch1 != '\r')      b64_putc('\r', fout);    b64_putc(ch, fout);    ch1 = ch;  }  b64_flush(fout);  fputc('\n', fout);}static void encode_8bit (FGETCONV *fc, FILE *fout, int istext){  int ch;    while ((ch = fgetconv (fc)) != EOF)    fputc (ch, fout);}  int mutt_write_mime_header (BODY *a, FILE *f){  PARAMETER *p;  char buffer[STRING];  char *t;  char *fn;  int len;  int tmplen;  int encode;    fprintf (f, "Content-Type: %s/%s", TYPE (a), a->subtype);  if (a->parameter)  {    len = 25 + mutt_strlen (a->subtype); /* approximate len. of content-type */    for(p = a->parameter; p; p = p->next)    {      char *tmp;            if(!p->value)	continue;            fputc (';', f);      buffer[0] = 0;      tmp = safe_strdup (p->value);      encode = rfc2231_encode_string (&tmp);      rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);      /* Dirty hack to make messages readable by Outlook Express        * for the Mac: force quotes around the boundary parameter       * even when they aren't needed.       */      if (!ascii_strcasecmp (p->attribute, "boundary") && !strcmp (buffer, tmp))	snprintf (buffer, sizeof (buffer), "\"%s\"", tmp);      FREE (&tmp);      tmplen = mutt_strlen (buffer) + mutt_strlen (p->attribute) + 1;      if (len + tmplen + 2 > 76)      {	fputs ("\n\t", f);	len = tmplen + 8;      }      else      {	fputc (' ', f);	len += tmplen + 1;      }      fprintf (f, "%s%s=%s", p->attribute, encode ? "*" : "", buffer);    }  }  fputc ('\n', f);  if (a->description)    fprintf(f, "Content-Description: %s\n", a->description);  fprintf (f, "Content-Disposition: %s", DISPOSITION (a->disposition));  if (a->use_disp)  {    if(!(fn = a->d_filename))      fn = a->filename;        if (fn)    {      char *tmp;      /* Strip off the leading path... */      if ((t = strrchr (fn, '/')))	t++;      else	t = fn;            buffer[0] = 0;      tmp = safe_strdup (t);      encode = rfc2231_encode_string (&tmp);      rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);      FREE (&tmp);      fprintf (f, "; filename%s=%s", encode ? "*" : "", buffer);    }  }  fputc ('\n', f);  if (a->encoding != ENC7BIT)    fprintf(f, "Content-Transfer-Encoding: %s\n", ENCODING (a->encoding));  /* Do NOT add the terminator here!!! */  return (ferror (f) ? -1 : 0);}# define write_as_text_part(a)  (mutt_is_text_part(a) \                                 || ((WithCrypto & APPLICATION_PGP)\                                      && mutt_is_application_pgp(a)))int mutt_write_mime_body (BODY *a, FILE *f){  char *p, boundary[SHORT_STRING];  char send_charset[SHORT_STRING];  FILE *fpin;  BODY *t;  FGETCONV *fc;    if (a->type == TYPEMULTIPART)  {    /* First, find the boundary to use */    if (!(p = mutt_get_parameter ("boundary", a->parameter)))    {      dprint (1, (debugfile, "mutt_write_mime_body(): no boundary parameter found!\n"));      mutt_error _("No boundary parameter found! [report this error]");      return (-1);    }    strfcpy (boundary, p, sizeof (boundary));    for (t = a->parts; t ; t = t->next)    {      fprintf (f, "\n--%s\n", boundary);      if (mutt_write_mime_header (t, f) == -1)	return -1;      fputc ('\n', f);      if (mutt_write_mime_body (t, f) == -1)	return -1;    }    fprintf (f, "\n--%s--\n", boundary);    return (ferror (f) ? -1 : 0);  }  /* This is pretty gross, but it's the best solution for now... */  if ((WithCrypto & APPLICATION_PGP)      && a->type == TYPEAPPLICATION      && mutt_strcmp (a->subtype, "pgp-encrypted") == 0)  {    fputs ("Version: 1\n", f);    return 0;  }  if ((fpin = fopen (a->filename, "r")) == NULL)  {    dprint(1,(debugfile, "write_mime_body: %s no longer exists!\n",a->filename));    mutt_error (_("%s no longer exists!"), a->filename);    return -1;  }  if (a->type == TYPETEXT && (!a->noconv))    fc = fgetconv_open (fpin, Charset, 			mutt_get_body_charset (send_charset, sizeof (send_charset), a),			0);  else    fc = fgetconv_open (fpin, 0, 0, 0);  if (a->encoding == ENCQUOTEDPRINTABLE)    encode_quoted (fc, f, write_as_text_part (a));  else if (a->encoding == ENCBASE64)    encode_base64 (fc, f, write_as_text_part (a));  else if (a->type == TYPETEXT && (!a->noconv))    encode_8bit (fc, f, write_as_text_part (a));  else    mutt_copy_stream (fpin, f);  fgetconv_close (&fc);  fclose (fpin);  return (ferror (f) ? -1 : 0);}#undef write_as_text_part#define BOUNDARYLEN 16void mutt_generate_boundary (PARAMETER **parm){  char rs[BOUNDARYLEN + 1];  char *p = rs;  int i;  rs[BOUNDARYLEN] = 0;  for (i=0;i<BOUNDARYLEN;i++)     *p++ = B64Chars[LRAND() % sizeof (B64Chars)];  *p = 0;    mutt_set_parameter ("boundary", rs, parm);}typedef struct{  int from;  int whitespace;  int dot;  int linelen;  int was_cr;}CONTENT_STATE;static void update_content_info (CONTENT *info, CONTENT_STATE *s, char *d, size_t dlen){  int from = s->from;  int whitespace = s->whitespace;  int dot = s->dot;  int linelen = s->linelen;  int was_cr = s->was_cr;  if (!d) /* This signals EOF */  {    if (was_cr)      info->binary = 1;    if (linelen > info->linemax)      info->linemax = linelen;    return;  }  for (; dlen; d++, dlen--)  {    char ch = *d;    if (was_cr)    {      was_cr = 0;      if (ch != '\n')      {        info->binary = 1;      }      else      {        if (whitespace) info->space = 1;	if (dot) info->dot = 1;        if (linelen > info->linemax) info->linemax = linelen;        whitespace = 0;	dot = 0;        linelen = 0;	continue;      }    }    linelen++;    if (ch == '\n')    {      info->crlf++;      if (whitespace) info->space = 1;      if (dot) info->dot = 1;      if (linelen > info->linemax) info->linemax = linelen;      whitespace = 0;      linelen = 0;      dot = 0;    }    else if (ch == '\r')    {      info->crlf++;      info->cr = 1;      was_cr = 1;      continue;    }    else if (ch & 0x80)      info->hibin++;    else if (ch == '\t' || ch == '\f')    {      info->ascii++;      whitespace++;    }    else if (ch < 32 || ch == 127)      info->lobin++;    else    {      if (linelen == 1)      {        if ((ch == 'F') || (ch == 'f'))          from = 1;        else          from = 0;        if (ch == '.')          dot = 1;        else          dot = 0;      }      else if (from)      {        if (linelen == 2 && ch != 'r') from = 0;        else if (linelen == 3 && ch != 'o') from = 0;        else if (linelen == 4)	{          if (ch == 'm') info->from = 1;          from = 0;        }      }      if (ch == ' ') whitespace++;      info->ascii++;    }    if (linelen > 1) dot = 0;    if (ch != ' ' && ch != '\t') whitespace = 0;  }  s->from = from;  s->whitespace = whitespace;  s->dot = dot;  s->linelen = linelen;  s->was_cr = was_cr;  }/* Define as 1 if iconv sometimes returns -1(EILSEQ) instead of transcribing. */#define BUGGY_ICONV 1/* * Find the best charset conversion of the file from fromcode into one * of the tocodes. If successful, set *tocode and CONTENT *info and * return the number of characters converted inexactly. If no * conversion was possible, return -1. * * We convert via UTF-8 in order to avoid the condition -1(EINVAL), * which would otherwise prevent us from knowing the number of inexact * conversions. Where the candidate target charset is UTF-8 we avoid * doing the second conversion because iconv_open("UTF-8", "UTF-8") * fails with some libraries. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -