📄 mime.cs
字号:
// $Id: MIME.cs,v 1.3 2006/08/07 08:15:36 ethem Exp $
namespace Erle
{
using System;
using System.IO;
using System.Text;
[Flags]
public enum SmtpEncode : byte
{
None = 0x00,
Dot = 0x01,
TrailingSoft = 0x02,
All = 0xff
}
public sealed class MIME
{
private MIME() { }
private static readonly byte[] crlf = Encoding.ASCII.GetBytes("\r\n");
private static readonly byte[] eq_crlf = Encoding.ASCII.GetBytes("=\r\n");
private static readonly byte[] eq_crlf_crlf = Encoding.ASCII.GetBytes("=\r\n\r\n");
private static readonly char[] hexChars =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
private static readonly byte[] hex =
{
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
(byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
};
#region encodemap
private const byte NUL = 0x00; // don't encode
private const byte ESC = 0x01; // always encode
private const byte SPC = 0x02; // horizontal whitespace
private const byte BOL = 0x03; // encode if at beginning of line
private const byte CR = 0x04; // carriage return
private const byte LF = 0x05; // linefeed
private static readonly byte[] encodemap =
{
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 000-007
ESC, SPC, LF, ESC, ESC, CR, ESC, ESC, // 010-017
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 020-027
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 030-037
SPC, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 040-047 !"#$%&'
NUL, NUL, NUL, NUL, NUL, NUL, BOL, NUL, // 050-057 ()*+,-./
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 060-067 01234567
NUL, NUL, NUL, NUL, NUL, ESC, NUL, NUL, // 070-077 89:;<=>?
NUL, NUL, NUL, NUL, NUL, NUL, BOL, NUL, // 100-107 @ABCDEFG
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 110-117 HIJKLMNO
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 120-127 PQRSTUVW
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 130-137 XYZ[\]^_
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 140-147 `abcdefg
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 150-157 hijklmno
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 160-167 pqrstuvw
NUL, NUL, NUL, NUL, NUL, NUL, NUL, ESC, // 170-177 xyz{|}~
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 200-207
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 210-217
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 220-227
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 230-237
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 240-247
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 250-257
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 260-267
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 270-277
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 300-307
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 310-317
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 320-327
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 330-337
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 340-347
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 350-357
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 360-367
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 370-377
};
#endregion
#region decodemap
private const byte DNUL = 0x7F;
private const byte DESC = 0x7E;
private const byte DCR = 0x7D;
private const byte DLF = 0x7C;
private static readonly byte[] decodemap =
{
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 000-007
DNUL, DNUL, DLF, DNUL, DNUL, DCR, DNUL, DNUL, // 010-017
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 020-027
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 030-037
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 040-047 !"#$%&'
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 050-057 ()*+,-./
0, 1, 2, 3, 4, 5, 6, 7, // 060-067 01234567
8, 9, DNUL, DNUL, DNUL, DESC, DNUL, DNUL, // 070-077 89:;<=>?
DNUL, 10, 11, 12, 13, 14, 15, DNUL, // 100-107 @ABCDEFG
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 110-117 HIJKLMNO
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 120-127 PQRSTUVW
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 130-137 XYZ[\]^_
DNUL, 10, 11, 12, 13, 14, 15, DNUL, // 140-147 `abcdefg
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 150-157 hijklmno
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 160-167 pqrstuvw
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 170-177 xyz{|}~
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 200-207
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 210-217
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 220-227
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 230-237
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 240-247
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 250-257
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 260-267
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 270-277
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 300-307
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 310-317
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 320-327
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 330-337
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 340-347
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 350-357
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 360-367
DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, DNUL, // 370-377
};
#endregion
#region QPEncode
public static byte[] QPEncode(byte[] originalBuffer)
{
return QPEncode(originalBuffer, SmtpEncode.All);
}
public static byte[] QPEncode(byte[] originalBuffer, SmtpEncode flags)
{
if (originalBuffer == null)
return null;
byte lastByte = NUL;
bool hadWhitespace = false;
int column = 0, buflen = originalBuffer.Length;
MemoryStream ms = new MemoryStream();
try
{
for (int i = 0; i < buflen; i++)
{
byte b = originalBuffer[i];
byte c = encodemap[b];
switch (c)
{
case NUL:
ms.WriteByte(b);
column++;
hadWhitespace = false;
break;
case SPC:
ms.WriteByte(b);
column++;
hadWhitespace = true;
break;
default:
if (c != LF || lastByte != CR)
{
switch (c)
{
case CR:
case LF:
if (hadWhitespace)
{
ms.Write(eq_crlf_crlf, 0, eq_crlf_crlf.Length);
hadWhitespace = false;
}
else
{
ms.Write(crlf, 0, crlf.Length);
}
column ^= column;
break;
default:
if ((c == BOL) && (column != 0) && ((flags & SmtpEncode.Dot) != SmtpEncode.None))
{
ms.WriteByte(b);
column++;
hadWhitespace = false;
}
else
{
ms.Write(new byte[] { (byte)'=', hex[0x0f & (b >> 4)], hex[0x0f & b] }, 0, 3);
column += 3;
hadWhitespace = false;
}
break;
}
}
break;
}
lastByte = c;
// ASSERT: Debug.Assert(column <= 76);
if (column >= 73)
{
ms.Write(eq_crlf, 0, eq_crlf.Length);
column ^= column;
hadWhitespace = false;
}
}
// need eof?
if (((flags & SmtpEncode.TrailingSoft) != SmtpEncode.None) && (column != 0))
ms.Write(eq_crlf, 0, eq_crlf.Length);
byte[] ret = ms.ToArray();
return ret;
}
catch
{
return null;
}
finally
{
ms.SetLength(0L);
ms.Capacity = 0;
ms.Close();
ms = null;
}
}
#endregion
#region QPDecode
public static byte[] QPDecode(byte[] decodedBuffer)
{
byte[] ret = null;
if (decodedBuffer != null)
{
int buflen = decodedBuffer.Length;
MemoryStream ms = new MemoryStream();
byte[] token = new byte[3];
int tokenLength = 0, i = 0;
try
{
while (i < buflen)
{
if (tokenLength == 0)
{
int j = i;
while (i < buflen && decodemap[decodedBuffer[i]] != DESC)
i++;
if (i != j)
ms.Write(decodedBuffer, j, i - j);
if (i >= buflen)
break;
}
byte b = decodedBuffer[i++];
byte c = decodemap[b];
token[tokenLength++] = b;
if (tokenLength == 3)
{
tokenLength ^= tokenLength;
// assert (decodemap[token[0]] == DESC)
byte n1 = decodemap[token[1]];
byte n2 = decodemap[token[2]];
if (n1 == DCR || n1 == DLF)
{ // "=\r", "=\n", or "=\r\n"
if (n1 == DLF || n2 != DLF)
{
if (n2 == DESC)
{
token[0] = token[2];
tokenLength = 1;
}
else
{
ms.WriteByte(token[2]);
}
}
}
else
{
if (n1 <= 15 || n2 <= 15)
{
ms.WriteByte((byte)((n1 << 4) | n2));
continue;
}
ms.Write(token, 0, token.Length);
}
}
}
ret = ms.ToArray();
}
catch
{
ret = null;
}
finally
{
ms.SetLength(0L);
ms.Capacity = 0;
ms.Close();
ms = null;
}
}
return ret;
}
#endregion
#region QEncode
internal static String QEncode(byte[] bufferOriginal, string charSet)
{
if (bufferOriginal == null) return String.Empty;
int bufferLen = bufferOriginal.Length;
if (bufferLen == 0) return String.Empty;
if (charSet == null || charSet == string.Empty)
charSet = Erle.DnsMail.MailInfo.DefaultCharset;
try
{
int nRead = 0; StringBuilder sb = new StringBuilder();
sb.Append("=?" + charSet + "?Q?");
char ch;
while (nRead < bufferLen)
{
ch = (char)bufferOriginal[nRead++];
if (((ch > 32 && ch < 61) || (ch > 61 && ch < 127)) && ch != '?' && ch != '_')
{
sb.Append(ch);
continue;
}
sb.Append('=');
sb.Append(hexChars[(ch >> 4) & 0x0f]);
sb.Append(hexChars[ch & 0x0f]);
}
sb.Append("?=");
return sb.ToString();
}
catch
{
return String.Empty;
}
finally
{
bufferOriginal = null;
}
}
#endregion
#region BEncode
internal static String BEncode(byte[] bufferOriginal, string charSet)
{
if (bufferOriginal == null) return String.Empty;
int bufferLen = bufferOriginal.Length;
if (bufferLen == 0) return String.Empty;
if (charSet == null || charSet == string.Empty)
charSet = Erle.DnsMail.MailInfo.DefaultCharset;
try
{
StringBuilder sb = new StringBuilder();
sb.Append("=?" + charSet + "?B?");
sb.Append(Convert.ToBase64String(bufferOriginal));
sb.Append("?=");
return sb.ToString();
}
catch
{
return String.Empty;
}
finally
{
bufferOriginal = null;
}
}
#endregion
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -