📄 wqkmime.pas
字号:
unit wqkMIME;
interface
{$DEFINE RangChecking}
uses Classes{$IFDEF RangeChecking}, SysUtils{$ENDIF};
function MimeEncodeString (const s: AnsiString): AnsiString;
function MimeDecodeString (const s: AnsiString): AnsiString;
Function SelectMimeDecodeStr(const s: AnsiString): AnsiString;
procedure MimeEncodeStream (const InputStream: TStream; const OutputStream: TStream);
procedure MimeDecodeStream (const InputStream: TStream; const OutputStream: TStream);
function MimeEncodedSize (const i: Integer): Integer;
function MimeDecodedSize (const i: Integer): Integer;
procedure MimeEncode (const InputBuffer: Pointer; const InputByteCount: Integer; const OutputBuffer: Pointer);
function MimeDecode (const InputBuffer: Pointer; const InputBytesCount: Integer; const OutputBuffer: Pointer): Integer;
function MimeDecodePartial (const InputBuffer: Pointer; const InputBytesCount: Integer; const OutputBuffer: Pointer; var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): Integer;
function MimeDecodePartialEnd (const OutputBuffer: Pointer; const ByteBuffer: Cardinal; const ByteBufferSpace: Cardinal): Integer;
function wqkDecodeString(const s: AnsiString):AnsiString;
{$IFDEF RangeChecking}
resourcestring
SInputBufferNil = 'MIME (Base64) Conversion: Input Buffer must not be NIL.';
SOutputBufferNil = 'MIME (Base64) Conversion: Output Buffer must not be NIL.';
{$ENDIF}
const
BUFFER_SIZE = $3000;
MIME_ENCODE_TABLE : array[ 0..63] of Byte = (
065, 066, 067, 068, 069, 070, 071, 072, // 00 - 07
073, 074, 075, 076, 077, 078, 079, 080, // 08 - 15
081, 082, 083, 084, 085, 086, 087, 088, // 16 - 23
089, 090, 097, 098, 099, 100, 101, 102, // 24 - 31
103, 104, 105, 106, 107, 108, 109, 110, // 32 - 39
111, 112, 113, 114, 115, 116, 117, 118, // 40 - 47
119, 120, 121, 122, 048, 049, 050, 051, // 48 - 55
052, 053, 054, 055, 056, 057, 043, 047); // 56 - 63
MIME_DECODE_TABLE : array[ Byte] of Cardinal = (
255, 255, 255, 255, 255, 255, 255, 255, // 00 - 07
255, 255, 255, 255, 255, 255, 255, 255, // 08 - 15
255, 255, 255, 255, 255, 255, 255, 255, // 16 - 23
255, 255, 255, 255, 255, 255, 255, 255, // 24 - 31
255, 255, 255, 255, 255, 255, 255, 255, // 32 - 39
255, 255, 255, 062, 255, 255, 255, 063, // 40 - 47
052, 053, 054, 055, 056, 057, 058, 059, // 48 - 55
060, 061, 255, 255, 255, 255, 255, 255, // 56 - 63
255, 000, 001, 002, 003, 004, 005, 006, // 64 - 71
007, 008, 009, 010, 011, 012, 013, 014, // 72 - 79
015, 016, 017, 018, 019, 020, 021, 022, // 80 - 87
023, 024, 025, 255, 255, 255, 255, 255, // 88 - 95
255, 026, 027, 028, 029, 030, 031, 032, // 96 - 103
033, 034, 035, 036, 037, 038, 039, 040, // 104 - 111
041, 042, 043, 044, 045, 046, 047, 048, // 112 - 119
049, 050, 051, 255, 255, 255, 255, 255, // 120 - 127
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255);
type
{$IFDEF RangeChecking}
EMime = class (Exception);
{$ENDIF}
PByte4 = ^TByte4;
TByte4 = packed record
b1: Byte;
b2: Byte;
b3: Byte;
b4: Byte;
end;
PByte3 = ^TByte3;
TByte3 = packed record
b1: Byte;
b2: Byte;
b3: Byte;
end;
implementation
{ **************************************************************************** }
{ Wrapper functions & procedures
{ **************************************************************************** }
function MimeEncodeString (const s: AnsiString): AnsiString;
label
NothingToDo;
var
l : Integer;
begin
if Pointer (s) = nil then goto NothingToDo;
{ l := length (s); }
l := Integer (Pointer (Integer (Pointer (s)) - 4)^);
SetString (Result, nil, MimeEncodedSize (l));
if Pointer (Result) = nil then goto NothingToDo;
MimeEncode (Pointer (s), l, Pointer (Result));
Exit;
NothingToDo:
Result := '';
end;
{ ********** }
function MimeDecodeString (const s: AnsiString): AnsiString;
label
NothingToDo;
var
ByteBuffer, ByteBufferSpace : Cardinal;
l : Integer;
begin
if Pointer (s) = nil then goto NothingToDo;
{ l := length (s); }
l := Integer (Pointer (Integer (Pointer (s)) - 4)^);
SetString (Result, nil, (l + 3) div 4 * 3);
if Pointer (Result) = nil then goto NothingToDo;
ByteBuffer := 0;
ByteBufferSpace := 4;
l := MimeDecodePartial (Pointer (s), l, Pointer (Result), ByteBuffer, ByteBufferSpace);
Inc (l, MimeDecodePartialEnd (Pointer (Integer (Result) + l), ByteBuffer, ByteBufferSpace));
SetLength (Result, l);
Exit;
NothingToDo:
Result := '';
end;
Function SelectMimeDecodeStr(const s: AnsiString): AnsiString;
begin
end;
{ **************************************************************************** }
procedure MimeEncodeStream (const InputStream: TStream; const OutputStream: TStream);
var
InputBuffer : array[ 0..BUFFER_SIZE - 1] of Byte;
OutputBuffer : array[ 0.. ((BUFFER_SIZE + 2) div 3) * 4 - 1] of Byte;
BytesRead : Integer;
begin
BytesRead := InputStream.Read (InputBuffer, SizeOf (InputBuffer));
while BytesRead = SizeOf (InputBuffer) do
begin
MimeEncode (@InputBuffer, SizeOf (InputBuffer), @OutputBuffer);
OutputStream.Write (OutputBuffer, SizeOf (OutputBuffer));
BytesRead := InputStream.Read (InputBuffer, SizeOf (InputBuffer));
end;
if BytesRead > 0 then
begin
MimeEncode (@InputBuffer, BytesRead, @OutputBuffer);
OutputStream.Write (OutputBuffer, MimeEncodedSize (BytesRead));
end;
end;
{ ********** }
procedure MimeDecodeStream (const InputStream: TStream; const OutputStream: TStream);
var
ByteBuffer, ByteBufferSpace : Cardinal;
InputBuffer : array[ 0..BUFFER_SIZE - 1] of Byte;
OutputBuffer : array[ 0.. (BUFFER_SIZE + 3) div 4 * 3 - 1] of Byte;
BytesRead : Integer;
begin
ByteBuffer := 0;
ByteBufferSpace := 4;
BytesRead := InputStream.Read (InputBuffer, SizeOf (InputBuffer));
while BytesRead > 0 do
begin
OutputStream.Write (OutputBuffer, MimeDecodePartial (@InputBuffer, BytesRead, @OutputBuffer, ByteBuffer, ByteBufferSpace));
BytesRead := InputStream.Read (InputBuffer, SizeOf (InputBuffer));
end;
OutputStream.Write (OutputBuffer, MimeDecodePartialEnd (@OutputBuffer, ByteBuffer, ByteBufferSpace));
end;
{ **************************************************************************** }
{ Helper functions
{ **************************************************************************** }
function MimeEncodedSize (const i: Integer): Integer;
begin
Result := (i + 2) div 3 * 4;
end;
function MimeDecodedSize (const i: Integer): Integer;
begin
Result := (i + 3) div 4 * 3;
end;
{ **************************************************************************** }
{ Primary functions & procedures
{ **************************************************************************** }
procedure MimeEncode (const InputBuffer: Pointer; const InputByteCount: Integer; const OutputBuffer: Pointer);
var
b : Cardinal;
InMax3 : Integer;
pIn, PInLimit : ^Byte;
POut : PByte4;
begin
{$IFDEF RangeChecking}
if InputBuffer = nil then raise EMime.Create (SInputBufferNil);
if OutputBuffer = nil then raise EMime.Create (SOutputBufferNil);
{$ENDIF}
if InputByteCount <= 0 then Exit;
pIn := InputBuffer;
InMax3 := InputByteCount div 3 * 3;
POut := OutputBuffer;
Integer (PInLimit) := Integer (pIn) + InMax3;
while pIn <> PInLimit do
begin
b := pIn^;
b := b shl 8;
Inc (pIn);
b := b or pIn^;
b := b shl 8;
Inc (pIn);
b := b or pIn^;
Inc (pIn);
// Write 4 bytes to OutputBuffer (in reverse order).
POut.b4 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b3 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b2 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b1 := MIME_ENCODE_TABLE[ b];
Inc (POut);
end;
case InputByteCount - InMax3 of
1:
begin
b := pIn^;
b := b shl 4;
POut.b2 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b1 := MIME_ENCODE_TABLE[ b];
POut.b3 := Ord ('='); // Fill remaining 2 bytes.
POut.b4 := Ord ('=');
end;
2:
begin
b := pIn^;
Inc (pIn);
b := b shl 8;
b := b or pIn^;
b := b shl 2;
POut.b3 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b2 := MIME_ENCODE_TABLE[ b and $3F];
b := b shr 6;
POut.b1 := MIME_ENCODE_TABLE[ b];
POut.b4 := Ord ('='); // Fill remaining byte.
end;
end;
end;
{ ********** }
function MimeDecode (const InputBuffer: Pointer; const InputBytesCount: Integer; const OutputBuffer: Pointer): Integer;
var
ByteBuffer, ByteBufferSpace : Cardinal;
begin
ByteBuffer := 0;
ByteBufferSpace := 4;
Result := MimeDecodePartial (InputBuffer, InputBytesCount, OutputBuffer, ByteBuffer, ByteBufferSpace);
Inc (Result, MimeDecodePartialEnd (Pointer (Integer (OutputBuffer) + Result), ByteBuffer, ByteBufferSpace));
end;
{ ********** }
function MimeDecodePartial (const InputBuffer: Pointer; const InputBytesCount: Integer; const OutputBuffer: Pointer; var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): Integer;
var
lByteBuffer, lByteBufferSpace, c: Cardinal;
pIn, PInLimit : ^Byte;
POut : PByte3;
begin
{$IFDEF RangeChecking}
if InputBuffer = nil then raise EMime.Create (SInputBufferNil);
if OutputBuffer = nil then raise EMime.Create (SOutputBufferNil);
{$ENDIF}
if InputBytesCount > 0 then
begin
pIn := InputBuffer;
Integer (PInLimit) := Integer (pIn) + InputBytesCount;
POut := OutputBuffer;
lByteBuffer := ByteBuffer;
lByteBufferSpace := ByteBufferSpace;
while pIn <> PInLimit do
begin
c := MIME_DECODE_TABLE[ pIn^]; // Read from InputBuffer.
Inc (pIn);
if c = $FF then Continue;
lByteBuffer := lByteBuffer shl 6;
lByteBuffer := lByteBuffer or c;
Dec (lByteBufferSpace);
if lByteBufferSpace <> 0 then Continue; // Read 4 bytes from InputBuffer?
POut.b3 := Byte (lByteBuffer); // Write 3 bytes to OutputBuffer (in reverse order).
lByteBuffer := lByteBuffer shr 8;
POut.b2 := Byte (lByteBuffer);
lByteBuffer := lByteBuffer shr 8;
POut.b1 := Byte (lByteBuffer);
lByteBuffer := 0;
Inc (POut);
lByteBufferSpace := 4;
end;
ByteBuffer := lByteBuffer;
ByteBufferSpace := lByteBufferSpace;
Result := Integer (POut) - Integer (OutputBuffer);
end
else
Result := 0;
end;
{ ********** }
function MimeDecodePartialEnd (const OutputBuffer: Pointer; const ByteBuffer: Cardinal; const ByteBufferSpace: Cardinal): Integer;
var
lByteBuffer : Cardinal;
begin
{$IFDEF RangeChecking}
if OutputBuffer = nil then raise EMime.Create (SOutputBufferNil);
{$ENDIF}
case ByteBufferSpace of
1:
begin
lByteBuffer := ByteBuffer shr 2;
PByte3 (OutputBuffer).b2 := Byte (lByteBuffer);
lByteBuffer := lByteBuffer shr 8;
PByte3 (OutputBuffer).b1 := Byte (lByteBuffer);
Result := 2;
end;
2:
begin
lByteBuffer := ByteBuffer shr 4;
PByte3 (OutputBuffer).b1 := Byte (lByteBuffer);
Result := 1;
end;
else
Result := 0;
end;
end;
function wqkDecodeString(const s: AnsiString):AnsiString;
var
i:integer;
s1,s2,s3:AnsiString;
begin
s1:='';
s1:=s[1]+s[2]+s[3];
s3:=s[1]+s[2];
if (s1<>' =?') and (s3<>'=?') then
begin
wqkDecodeString:=s;
exit;
end else
for i:=12 to length(s)-2 do
s2:=s2+s[i];
wqkDecodeString:=MimeDecodeString(s2);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -