📄 jclmime.pas
字号:
B := InPtr^.B1;
B := B shl 8;
B := B or InPtr^.B2;
B := B shl 8;
B := B or InPtr^.B3;
Inc(InPtr);
{ Write 4 bytes to OutputBuffer (in reverse order). }
OutPtr^.B4 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B3 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B1 := MIME_ENCODE_TABLE[B];
Inc(OutPtr);
until Cardinal(InPtr) >= InnerLimit;
{ Write line break (CRLF). }
OutPtr^.B1 := 13;
OutPtr^.B2 := 10;
Inc(Cardinal(OutPtr), 2);
Inc(InnerLimit, MIME_DECODED_LINE_BREAK);
until InnerLimit > OuterLimit;
end;
procedure MimeEncodeNoCRLF(const InputBuffer; const InputByteCount: Cardinal; out OutputBuffer);
var
B, InnerLimit, OuterLimit: Cardinal;
InPtr: PByte3;
OutPtr: PByte4;
begin
if InputByteCount = 0 then
Exit;
InPtr := @InputBuffer;
OutPtr := @OutputBuffer;
OuterLimit := InputByteCount div 3 * 3;
InnerLimit := Cardinal(InPtr);
Inc(InnerLimit, OuterLimit);
{ Last line loop. }
while Cardinal(InPtr) < InnerLimit do
begin
{ Read 3 bytes from InputBuffer. }
B := InPtr^.B1;
B := B shl 8;
B := B or InPtr^.B2;
B := B shl 8;
B := B or InPtr^.B3;
Inc(InPtr);
{ Write 4 bytes to OutputBuffer (in reverse order). }
OutPtr^.B4 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B3 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr^.B1 := MIME_ENCODE_TABLE[B];
Inc(OutPtr);
end;
{ End of data & padding. }
case InputByteCount - OuterLimit of
1:
begin
B := InPtr^.B1;
B := B shl 4;
OutPtr.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr.B1 := MIME_ENCODE_TABLE[B];
OutPtr.B3 := MIME_PAD_CHAR; { Pad remaining 2 bytes. }
OutPtr.B4 := MIME_PAD_CHAR;
end;
2:
begin
B := InPtr^.B1;
B := B shl 8;
B := B or InPtr^.B2;
B := B shl 2;
OutPtr.B3 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr.B1 := MIME_ENCODE_TABLE[B];
OutPtr.B4 := MIME_PAD_CHAR; { Pad remaining byte. }
end;
end;
end;
// Decoding Core
function MimeDecode(const InputBuffer; const InputBytesCount: Cardinal; out OutputBuffer): Cardinal;
var
ByteBuffer, ByteBufferSpace: Cardinal;
begin
ByteBuffer := 0;
ByteBufferSpace := 4;
Result := MimeDecodePartial(InputBuffer, InputBytesCount, OutputBuffer, ByteBuffer, ByteBufferSpace);
Inc(Result, MimeDecodePartialEnd(Pointer(Cardinal(@OutputBuffer) + Result)^, ByteBuffer, ByteBufferSpace));
end;
function MimeDecodePartial(const InputBuffer; const InputBytesCount: Cardinal; out OutputBuffer; var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): Cardinal;
var
LByteBuffer, LByteBufferSpace, C: Cardinal;
InPtr, OuterLimit: ^Byte;
OutPtr: PByte3;
begin
if InputBytesCount > 0 then
begin
InPtr := @InputBuffer;
Cardinal(OuterLimit) := Cardinal(InPtr) + InputBytesCount;
OutPtr := @OutputBuffer;
LByteBuffer := ByteBuffer;
LByteBufferSpace := ByteBufferSpace;
while InPtr <> OuterLimit do
begin
{ Read from InputBuffer. }
C := MIME_DECODE_TABLE[InPtr^];
Inc(InPtr);
if C = $FF then Continue;
LByteBuffer := LByteBuffer shl 6;
LByteBuffer := LByteBuffer or C;
Dec(LByteBufferSpace);
{ Have we read 4 bytes from InputBuffer? }
if LByteBufferSpace <> 0 then Continue;
{ Write 3 bytes to OutputBuffer (in reverse order). }
OutPtr^.B3 := Byte(LByteBuffer);
LByteBuffer := LByteBuffer shr 8;
OutPtr^.B2 := Byte(LByteBuffer);
LByteBuffer := LByteBuffer shr 8;
OutPtr^.B1 := Byte(LByteBuffer);
LByteBuffer := 0;
Inc(OutPtr);
LByteBufferSpace := 4;
end;
ByteBuffer := LByteBuffer;
ByteBufferSpace := LByteBufferSpace;
Result := Cardinal(OutPtr) - Cardinal(@OutputBuffer);
end
else
Result := 0;
end;
function MimeDecodePartialEnd(out OutputBuffer; const ByteBuffer: Cardinal; const ByteBufferSpace: Cardinal): Cardinal;
var
LByteBuffer: Cardinal;
begin
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;
// File Encoding & Decoding
procedure MimeEncodeFile(const InputFileName, OutputFileName: AnsiString);
var
InputStream, OutputStream: TFileStream;
begin
InputStream := TFileStream.Create(InputFileName, fmOpenRead or fmShareDenyWrite);
try
OutputStream := TFileStream.Create(OutputFileName, fmCreate);
try
MimeEncodeStream(InputStream, OutputStream);
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
procedure MimeEncodeFileNoCRLF(const InputFileName, OutputFileName: AnsiString);
var
InputStream, OutputStream: TFileStream;
begin
InputStream := TFileStream.Create(InputFileName, fmOpenRead or fmShareDenyWrite);
try
OutputStream := TFileStream.Create(OutputFileName, fmCreate);
try
MimeEncodeStreamNoCRLF(InputStream, OutputStream);
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
procedure MimeDecodeFile(const InputFileName, OutputFileName: AnsiString);
var
InputStream, OutputStream: TFileStream;
begin
InputStream := TFileStream.Create(InputFileName, fmOpenRead or fmShareDenyWrite);
try
OutputStream := TFileStream.Create(OutputFileName, fmCreate);
try
MimeDecodeStream(InputStream, OutputStream);
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
// Stream Encoding & Decoding
procedure MimeEncodeStream(const InputStream: TStream; const OutputStream: TStream);
var
InputBuffer: array [0..MIME_BUFFER_SIZE - 1] of Byte;
OutputBuffer: array [0..(MIME_BUFFER_SIZE + 2) div 3 * 4 + MIME_BUFFER_SIZE div MIME_DECODED_LINE_BREAK * 2 - 1] of Byte;
BytesRead: Cardinal;
IDelta, ODelta: Cardinal;
begin
BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
while BytesRead = SizeOf(InputBuffer) do
begin
MimeEncodeFullLines(InputBuffer, SizeOf(InputBuffer), OutputBuffer);
OutputStream.Write(OutputBuffer, SizeOf(OutputBuffer));
BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
end;
MimeEncodeFullLines(InputBuffer, BytesRead, OutputBuffer);
IDelta := BytesRead div MIME_DECODED_LINE_BREAK; // Number of lines processed.
ODelta := IDelta * (MIME_ENCODED_LINE_BREAK + 2);
IDelta := IDelta * MIME_DECODED_LINE_BREAK;
MimeEncodeNoCRLF(Pointer(Cardinal(@InputBuffer) + IDelta)^, BytesRead - IDelta, Pointer(Cardinal(@OutputBuffer) + ODelta)^);
OutputStream.Write(OutputBuffer, MimeEncodedSize(BytesRead));
end;
procedure MimeEncodeStreamNoCRLF(const InputStream: TStream; const OutputStream: TStream);
var
InputBuffer: array [0..MIME_BUFFER_SIZE - 1] of Byte;
OutputBuffer: array [0..((MIME_BUFFER_SIZE + 2) div 3) * 4 - 1] of Byte;
BytesRead: Cardinal;
begin
BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
while BytesRead = SizeOf(InputBuffer) do
begin
MimeEncodeNoCRLF(InputBuffer, SizeOf(InputBuffer), OutputBuffer);
OutputStream.Write(OutputBuffer, SizeOf(OutputBuffer));
BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
end;
MimeEncodeNoCRLF(InputBuffer, BytesRead, OutputBuffer);
OutputStream.Write(OutputBuffer, MimeEncodedSizeNoCRLF(BytesRead));
end;
procedure MimeDecodeStream(const InputStream: TStream; const OutputStream: TStream);
var
ByteBuffer, ByteBufferSpace: Cardinal;
InputBuffer: array [0..MIME_BUFFER_SIZE - 1] of Byte;
OutputBuffer: array [0..(MIME_BUFFER_SIZE + 3) div 4 * 3 - 1] of Byte;
BytesRead: Cardinal;
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;
// History:
// $Log: JclMime.pas,v $
// Revision 1.13 2005/02/24 16:34:40 marquardt
// remove divider lines, add section lines (unfinished)
//
// Revision 1.12 2005/02/13 22:24:25 rrossmair
// moved PCardinal declaration from JclMime to JclBase
//
// Revision 1.11 2004/10/13 06:58:19 marquardt
// normal style cleaning
//
// Revision 1.10 2004/10/12 18:29:52 rrossmair
// cleanup
//
// Revision 1.9 2004/07/28 18:00:51 marquardt
// various style cleanings, some minor fixes
//
// Revision 1.8 2004/07/07 22:34:25 mthoma
// Added Ralf MimeStreams and MimeFile utilities...
//
// Revision 1.7 2004/06/14 13:05:18 marquardt
// style cleaning ENDIF, Tabs
//
// Revision 1.6 2004/05/05 00:09:59 mthoma
// Updated headers: Added donors as contributors, adjusted the initial authors, added cvs names when they were not obvious. Changed $data to $date where necessary,
//
// Revision 1.5 2004/04/09 20:21:11 mthoma
// Updated to Ralfs latest release. That also fixed 0000406.
//
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -