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

📄 unmime.c

📁 用于对收发邮件编码进行解码的类文件,功能简洁
💻 C
📖 第 1 页 / 共 2 页
字号:
int MimeBodyType(unsigned char *hdrs, int WantDecode)
{
  unsigned char *NxtHdr = hdrs;
  unsigned char *XferEnc, *XferEncOfs, *CntType, *MimeVer, *p;
  int  HdrsFound = 0;     /* We only look for three headers */
  int  BodyType;          /* Return value */ 

  /* Setup for a standard (no MIME, no QP, 7-bit US-ASCII) message */
  MultipartDelimiter[0] = '\0';
  CurrEncodingIsQP = 0;
  BodyState = S_BODY_DATA;
  BodyType = 0;

  /* Just in case ... */
  if (hdrs == NULL)
    return BodyType;

  XferEnc = XferEncOfs = CntType = MimeVer = NULL;

  do {
    if (strncasecmp("Content-Transfer-Encoding:", NxtHdr, 26) == 0) {
      XferEncOfs = NxtHdr;
      p = nxtaddr(NxtHdr);
      if (p != NULL) {
	xalloca(XferEnc, char *, strlen(p) + 1);
	strcpy(XferEnc, p);
	HdrsFound++;
      }
    }
    else if (strncasecmp("Content-Type:", NxtHdr, 13) == 0) {
      /*
       * This one is difficult. We cannot use the standard
       * nxtaddr() routine, since the boundary-delimiter is
       * (probably) enclosed in quotes - and thus appears
       * as an rfc822 comment, and nxtaddr() "eats" up any
       * spaces in the delimiter. So, we have to do this
       * by hand.
       */

      /* Skip the "Content-Type:" part and whitespace after it */
      for (NxtHdr += 13; ((*NxtHdr == ' ') || (*NxtHdr == '\t')); NxtHdr++);

      /* 
       * Get the full value of the Content-Type header;
       * it might span multiple lines. So search for
       * a newline char, but ignore those that have a
       * have a TAB or space just after the NL (continued
       * lines).
       */
      p = NxtHdr-1;
      do {
        p=strchr((p+1),'\n'); 
      } while ( (p != NULL) && ((*(p+1) == '\t') || (*(p+1) == ' ')) );
      if (p == NULL) p = NxtHdr + strlen(NxtHdr);

      xalloca(CntType, char *, p-NxtHdr+2);
      strncpy(CntType, NxtHdr, (p-NxtHdr));
      *(CntType+(p-NxtHdr)) = '\0';
      HdrsFound++;
    }
    else if (strncasecmp("MIME-Version:", NxtHdr, 13) == 0) {
      p = nxtaddr(NxtHdr);
      if (p != NULL) {
	xalloca(MimeVer, char *, strlen(p) + 1);
	strcpy(MimeVer, p);
	HdrsFound++;
      }
    }

    NxtHdr = (strchr(NxtHdr, '\n'));
    if (NxtHdr != NULL) NxtHdr++;
  } while ((NxtHdr != NULL) && (*NxtHdr) && (HdrsFound != 3));


  /* Done looking through the headers, now check what they say */
  if ((MimeVer != NULL) && (strcmp(MimeVer, "1.0") == 0)) {

    /* Check Content-Type to see if this is a multipart message */
    if ( (CntType != NULL) &&
         ((strncasecmp(CntType, "multipart/", 10) == 0) ||
	  (strncasecmp(CntType, "message/", 8) == 0)) ) {

      char *p1 = GetBoundary(CntType);

      if (p1 != NULL) {
	/* The actual delimiter is "--" followed by 
	   the boundary string */
	strcpy(MultipartDelimiter, "--");
	strncat(MultipartDelimiter, p1, MAX_DELIM_LEN);
	BodyType = (MSG_IS_8BIT | MSG_NEEDS_DECODE);
      }
    }

    /* 
     * Check Content-Transfer-Encoding, but
     * ONLY for non-multipart messages (BodyType == 0).
     */
    if ((XferEnc != NULL) && (BodyType == 0)) {
      if (strcasecmp(XferEnc, "quoted-printable") == 0) {
	CurrEncodingIsQP = 1;
	BodyType = (MSG_IS_8BIT | MSG_NEEDS_DECODE);
	if (WantDecode) {
           SetEncoding8bit(XferEncOfs);
        }
      }
      else if (strcasecmp(XferEnc, "7bit") == 0) {
	CurrEncodingIsQP = 0;
	BodyType = (MSG_IS_7BIT);
      }
      else if (strcasecmp(XferEnc, "8bit") == 0) {
	CurrEncodingIsQP = 0;
	BodyType = (MSG_IS_8BIT);
      }
    }

  }

  return BodyType;
}


/*
 * Decode one line of data containing QP data.
 * Return flag set if this line ends with a soft line-break.
 * 'bufp' is modified to point to the end of the output buffer.
 */
static int DoOneQPLine(unsigned char **bufp, int collapsedoubledot)
{
  unsigned char *buf = *bufp;
  unsigned char *p_in, *p_out, *p;
  int n;
  int ret = 0;

  p_in = buf;
  if (collapsedoubledot && (strncmp(buf, "..", 2) == 0))
    p_in++;

  for (p_out = buf; (*p_in); ) {
    p = strchr(p_in, '=');
    if (p == NULL) {
      /* No more QP data, just move remainder into place */
      n = strlen(p_in);
      memmove(p_out, p_in, n);
      p_in += n; p_out += n;
    }
    else {
      if (p > p_in) {
	/* There are some uncoded chars at the beginning. */
	n = (p - p_in);
	memmove(p_out, p_in, n);
	p_out += n;
      }
              
      switch (*(p+1)) {
      case '\0': case '\r': case '\n':
	/* Soft line break, skip '=' */
	p_in = p+1; 
	if (*p_in == '\r') p_in++;
	if (*p_in == '\n') p_in++;
        ret = 1;
	break;

      default:
	/* There is a QP encoded byte */
	if (qp_char(*(p+1), *(p+2), p_out) == 0) {
	  p_in = p+3;
	}
	else {
	  /* Invalid QP data - pass through unchanged. */
	  *p_out = '=';
	  p_in = p+1;
	}
	p_out++;
	break;
      }
    }
  }

  *p_out = '\0';
  *bufp = p_out;
  return ret;
}


/* This is called once per line in the message body.  We need to scan
 * all lines in the message body for the multipart delimiter string,
 * and handle any body-part headers in such messages (these can toggle
 * qp-decoding on and off).
 *
 * Note: Messages that are NOT multipart-messages go through this
 * routine quickly, since BodyState will always be S_BODY_DATA,
 * and MultipartDelimiter is NULL.
 *
 * Return flag set if this line ends with a soft line-break.
 * 'bufp' is modified to point to the end of the output buffer.
 */

int UnMimeBodyline(unsigned char **bufp, int collapsedoubledot)
{
  unsigned char *buf = *bufp;
  int ret = 0;

  switch (BodyState) {
  case S_BODY_HDR:
    UnMimeHeader(buf);   /* Headers in body-parts can be encoded, too! */
    if (strncasecmp("Content-Transfer-Encoding:", buf, 26) == 0) {
      char *XferEnc;

      XferEnc = nxtaddr(buf);
      if ((XferEnc != NULL) && (strcasecmp(XferEnc, "quoted-printable") == 0)) {
	CurrEncodingIsQP = 1;
	SetEncoding8bit(buf);
      }
    }
    else if ((*buf == '\0') || (*buf == '\n') || (strcmp(buf, "\r\n") == 0))
      BodyState = S_BODY_DATA;

    *bufp = (buf + strlen(buf));
    break;

  case S_BODY_DATA:
    if ((*MultipartDelimiter) && 
	(strncmp(buf, MultipartDelimiter, strlen(MultipartDelimiter)) == 0)) {
      BodyState = S_BODY_HDR;
      CurrEncodingIsQP = 0;
    }

    if (CurrEncodingIsQP) 
      ret = DoOneQPLine(bufp, collapsedoubledot);
    else
     *bufp = (buf + strlen(buf));
    break;
  }

  return ret;
}


#ifdef STANDALONE
#include <stdio.h>
#include <unistd.h>

char *program_name = "unmime";

#define BUFSIZE_INCREMENT 4096

#ifdef DEBUG
#define DBG_FWRITE(B,L,BS,FD) fwrite(B, L, BS, FD)
#else
#define DBG_FWRITE(B,L,BS,FD)
#endif

int main(int argc, char *argv[])
{
  unsigned int BufSize;
  unsigned char *buffer, *buf_p;
  int nl_count, i, bodytype;

#ifdef DEBUG
  pid_t pid;
  FILE *fd_orig, *fd_conv;
  char fnam[100];

  pid = getpid();
  sprintf(fnam, "/tmp/i_unmime.%x", pid);
  fd_orig = fopen(fnam, "w");
  sprintf(fnam, "/tmp/o_unmime.%x", pid);
  fd_conv = fopen(fnam, "w");
#endif

  BufSize = BUFSIZE_INCREMENT;    /* Initial size of buffer */
  buf_p = buffer = (unsigned char *) xmalloc(BufSize);
  nl_count = 0;

  do {
    i = fread(buf_p, 1, 1, stdin);
    switch (*buf_p) {
     case '\n':
       nl_count++;
       break;

     case '\r':
       break;

     default:
       nl_count = 0;
       break;
    }

    buf_p++;
    if ((buf_p - buffer) == BufSize) {
       /* Buffer is full! Get more room. */
       buffer = xrealloc(buffer, BufSize+BUFSIZE_INCREMENT);
       buf_p = buffer + BufSize;
       BufSize += BUFSIZE_INCREMENT;
    }
  } while ((i > 0) && (nl_count < 2));

  *buf_p = '\0';
  DBG_FWRITE(buffer, strlen(buffer), 1, fd_orig);

  UnMimeHeader(buffer);
  bodytype = MimeBodyType(buffer, 1);

  i = strlen(buffer);
  fwrite(buffer, i, 1, stdout);
  DBG_FWRITE(buffer, i, 1, fd_conv);
  
  do {
     buf_p = (buffer - 1);
     do {
        buf_p++;
        i = fread(buf_p, 1, 1, stdin);
     } while ((i == 1) && (*buf_p != '\n'));
     if (i == 1) buf_p++;
     *buf_p = '\0';
     DBG_FWRITE(buf, (buf_p - buffer), 1, fd_orig);

     if (buf_p > buffer) {
        if (bodytype & MSG_NEEDS_DECODE) {
           buf_p = buffer;
           UnMimeBodyline(&buf_p, 0);
        }
        fwrite(buffer, (buf_p - buffer), 1, stdout);
        DBG_FWRITE(buffer, (buf_p - buffer), 1, fd_conv);
     }
  } while (buf_p > buffer);

  free(buffer);
  fflush(stdout);

#ifdef DEBUG
  fclose(fd_orig);
  fclose(fd_conv);
#endif

  return 0;
}
#endif

⌨️ 快捷键说明

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