📄 dimime.pas
字号:
{ ---------- }
procedure DecodeHttpBasicAuthentication(const BasicCredentials: AnsiString; out UserId, PassWord: AnsiString);
label
Fail;
const
LBasic = 6; { Length ('Basic ') }
var
DecodedPtr, P: PAnsiChar;
I, L: Cardinal;
begin
P := Pointer(BasicCredentials);
if P = nil then goto Fail;
L := Cardinal(Pointer(P - 4)^);
if L <= LBasic then goto Fail;
Dec(L, LBasic);
Inc(P, LBasic);
GetMem(DecodedPtr, MimeDecodedSize(L));
L := MimeDecode(P^, L, DecodedPtr^);
{ Look for colon (':'). }
I := 0;
P := DecodedPtr;
while (L > 0) and (P[I] <> ':') do
begin
Inc(I);
Dec(L);
end;
{ Store UserId and Password. }
SetString(UserId, DecodedPtr, I);
if L > 1 then
SetString(PassWord, DecodedPtr + I + 1, L - 1)
else
PassWord := '';
FreeMem(DecodedPtr);
Exit;
Fail:
UserId := '';
PassWord := '';
end;
{ ---------------------------------------------------------------------------- }
{ Size Functions
{ ---------------------------------------------------------------------------- }
function MimeEncodedSize(const InputSize: Cardinal): Cardinal;
begin
if InputSize > 0 then
Result := (InputSize + 2) div 3 * 4 + (InputSize - 1) div MIME_DECODED_LINE_BREAK * 2
else
Result := InputSize;
end;
{ ---------- }
function MimeEncodedSizeNoCRLF(const InputSize: Cardinal): Cardinal;
begin
Result := (InputSize + 2) div 3 * 4;
end;
{ ---------- }
function MimeDecodedSize(const InputSize: Cardinal): Cardinal;
begin
Result := (InputSize + 3) div 4 * 3;
end;
{ ---------------------------------------------------------------------------- }
{ Encoding Core
{ ---------------------------------------------------------------------------- }
procedure MimeEncode(const InputBuffer; const InputByteCount: Cardinal; out OutputBuffer);
var
IDelta, ODelta: Cardinal;
begin
MimeEncodeFullLines(InputBuffer, InputByteCount, OutputBuffer);
IDelta := InputByteCount div MIME_DECODED_LINE_BREAK; // Number of lines processed so far.
ODelta := IDelta * (MIME_ENCODED_LINE_BREAK + 2);
IDelta := IDelta * MIME_DECODED_LINE_BREAK;
MimeEncodeNoCRLF(Pointer(Cardinal(@InputBuffer) + IDelta)^, InputByteCount - IDelta, Pointer(Cardinal(@OutputBuffer) + ODelta)^);
end;
{ ---------- }
procedure MimeEncodeFullLines(const InputBuffer; const InputByteCount: Cardinal; out OutputBuffer);
var
B, InnerLimit, OuterLimit: Cardinal;
InPtr: PByte3;
OutPtr: PByte4;
begin
{ Do we have enough input to encode a full line? }
if InputByteCount < MIME_DECODED_LINE_BREAK then Exit;
InPtr := @InputBuffer;
OutPtr := @OutputBuffer;
InnerLimit := Cardinal(InPtr);
Inc(InnerLimit, MIME_DECODED_LINE_BREAK);
OuterLimit := Cardinal(InPtr);
Inc(OuterLimit, InputByteCount);
{ Multiple line loop. }
repeat
{ Single line loop. }
repeat
{ 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);
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;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -