type
PPacket = ^TPacket;
TPacket = packed record
case Integer of
0: (b0, b1, b2, b3: Byte);
1: (i: Integer);
2: (a: array[0..3] of Byte);
3: (c: array[0..3] of Char);
end;
procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PChar);
begin
OutBuf[0] := EnCodeTable[Packet.a[0] shr 2];
OutBuf[1] := EnCodeTable[((Packet.a[0] shl 4) or (Packet.a[1] shr 4)) and $0000003f];
if NumChars < 2 then
OutBuf[2] := '='
else OutBuf[2] := EnCodeTable[((Packet.a[1] shl 2) or (Packet.a[2] shr 6)) and $0000003f];
if NumChars < 3 then
OutBuf[3] := '='
else OutBuf[3] := EnCodeTable[Packet.a[2] and $0000003f];
end;
function DecodePacket(InBuf: PChar; var nChars: Integer): TPacket;
begin
Result.a[0] := (DecodeTable[InBuf[0]] shl 2) or
(DecodeTable[InBuf[1]] shr 4);
NChars := 1;
if InBuf[2] <> '=' then
begin
Inc(NChars);
Result.a[1] := (DecodeTable[InBuf[1]] shl 4) or
(DecodeTable[InBuf[2]] shr 2);
end;
if InBuf[3] <> '=' then
begin
Inc(NChars);
Result.a[2] := (DecodeTable[InBuf[2]] shl 6) or DecodeTable[InBuf[3]];
end;
end;
procedure EncodeStream(Input, Output: TStream);
type
PInteger = ^Integer;
var
InBuf: array[0..509] of Byte;
OutBuf: array[0..1023] of Char;
BufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
begin
K := 0;
repeat
BytesRead := Input.Read(InBuf, SizeOf(InBuf));
I := 0;
BufPtr := OutBuf;
while I < BytesRead do
begin
if BytesRead - I < 3 then
J := BytesRead - I
else J := 3;
Packet.i := 0;
Packet.b0 := InBuf[I];
if J > 1 then
Packet.b1 := InBuf[I + 1];
if J > 2 then
Packet.b2 := InBuf[I + 2];
EncodePacket(Packet, J, BufPtr);
Inc(I, 3);
Inc(BufPtr, 4);
Inc(K, 4);
if K > 75 then
begin
BufPtr[0] := #$0D;
BufPtr[1] := #$0A;
Inc(BufPtr, 2);
K := 0;
end;
end;
Output.Write(Outbuf, BufPtr - PChar(@OutBuf));
until BytesRead = 0;
end;
procedure DecodeStream(Input, Output: TStream);
var
InBuf: array[0..75] of Char;
OutBuf: array[0..49] of Byte;
InBufPtr, OutBufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
procedure SkipWhite;
var
C: Char;
NumRead: Integer;
begin
while True do
begin
NumRead := Input.Read(C, 1);
if NumRead = 1 then
begin
if C in ['0'..'9','A'..'Z','a'..'z','+','/','='] then
begin
Input.Position := Input.Position - 1;
Break;
end;
end else Break;
end;
end;
begin
repeat
SkipWhite;
BytesRead := Input.Read(InBuf, SizeOf(InBuf));
InBufPtr := InBuf;
OutBufPtr := @OutBuf;
I := 0;
while I < BytesRead do
begin
Packet := DecodePacket(InBufPtr, J);
K := 0;
while J > 0 do
begin
OutBufPtr^ := Char(Packet.a[K]);
Inc(OutBufPtr);
Dec(J);
Inc(K);
end;
Inc(InBufPtr, 4);
Inc(I, 4);
end;
Output.Write(OutBuf, OutBufPtr - PChar(@OutBuf));
until BytesRead = 0;
end;
function EncodeString(const Input: string): string;
var
I, K, J: Integer;
Packet: TPacket;
begin
Result := '';
I := (Length(Input) div 3) * 4;
if Length(Input) mod 3 > 0 then Inc(I, 4);
SetLength(Result, I);
J := 1;
for I := 1 to Length(Input) div 3 do
begin
Packet.i := 0;
Packet.a[0] := Byte(Input[(I - 1) * 3 + 1]);
Packet.a[1] := Byte(Input[(I - 1) * 3 + 2]);
Packet.a[2] := Byte(Input[(I - 1) * 3 + 3]);
EncodePacket(Packet, 3, PChar(@Result[J]));
Inc(J, 4);
end;
K := 0;
Packet.i := 0;
for I := Length(Input) - (Length(Input) mod 3) + 1 to Length(Input) do
begin
Packet.a[K] := Byte(Input[I]);
Inc(K);
if I = Length(Input) then
EncodePacket(Packet, Length(Input) mod 3, PChar(@Result[J]));
end;
end;
function DecodeString(const Input: string): string;
var
I, J, K: Integer;
Packet: TPacket;
begin
Result := '';
for I := 1 to Length(Input) div 4 do
begin
Packet := DecodePacket(PChar(@Input[(I - 1) * 4 + 1]), J);
K := 0;
while J > 0 do
begin
Result := Result + Packet.c[K];
Inc(K);
Dec(J);
end;
end;
end;
type
PPacket = ^TPacket;
TPacket = packed record
case Integer of
0: (b0, b1, b2, b3: Byte);
1: (i: Integer);
2: (a: array[0..3] of Byte);
3: (c: array[0..3] of Char);
end;
procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PChar);
begin
OutBuf[0] := EnCodeTable[Packet.a[0] shr 2];
OutBuf[1] := EnCodeTable[((Packet.a[0] shl 4) or (Packet.a[1] shr 4)) and $0000003f];
if NumChars < 2 then
OutBuf[2] := '='
else OutBuf[2] := EnCodeTable[((Packet.a[1] shl 2) or (Packet.a[2] shr 6)) and $0000003f];
if NumChars < 3 then
OutBuf[3] := '='
else OutBuf[3] := EnCodeTable[Packet.a[2] and $0000003f];
end;
function DecodePacket(InBuf: PChar; var nChars: Integer): TPacket;
begin
Result.a[0] := (DecodeTable[InBuf[0]] shl 2) or
(DecodeTable[InBuf[1]] shr 4);
NChars := 1;
if InBuf[2] <> '=' then
begin
Inc(NChars);
Result.a[1] := (DecodeTable[InBuf[1]] shl 4) or
(DecodeTable[InBuf[2]] shr 2);
end;
if InBuf[3] <> '=' then
begin
Inc(NChars);
Result.a[2] := (DecodeTable[InBuf[2]] shl 6) or DecodeTable[InBuf[3]];
end;
end;
procedure EncodeStream(Input, Output: TStream);
type
PInteger = ^Integer;
var
InBuf: array[0..509] of Byte;
OutBuf: array[0..1023] of Char;
BufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
begin
K := 0;
repeat
BytesRead := Input.Read(InBuf, SizeOf(InBuf));
I := 0;
BufPtr := OutBuf;
while I < BytesRead do
begin
if BytesRead - I < 3 then
J := BytesRead - I
else J := 3;
Packet.i := 0;
Packet.b0 := InBuf[I];
if J > 1 then
Packet.b1 := InBuf[I + 1];
if J > 2 then
Packet.b2 := InBuf[I + 2];
EncodePacket(Packet, J, BufPtr);
Inc(I, 3);
Inc(BufPtr, 4);
Inc(K, 4);
if K > 75 then
begin
BufPtr[0] := #$0D;
BufPtr[1] := #$0A;
Inc(BufPtr, 2);
K := 0;
end;
end;
Output.Write(Outbuf, BufPtr - PChar(@OutBuf));
until BytesRead = 0;
end;
procedure DecodeStream(Input, Output: TStream);
var
InBuf: array[0..75] of Char;
OutBuf: array[0..49] of Byte;
InBufPtr, OutBufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
procedure SkipWhite;
var
C: Char;
NumRead: Integer;
begin
while True do
begin
NumRead := Input.Read(C, 1);
if NumRead = 1 then
begin
if C in ['0'..'9','A'..'Z','a'..'z','+','/','='] then
begin
Input.Position := Input.Position - 1;
Break;
end;
end else Break;
end;
end;
begin
repeat
SkipWhite;
BytesRead := Input.Read(InBuf, SizeOf(InBuf));
InBufPtr := InBuf;
OutBufPtr := @OutBuf;
I := 0;
while I < BytesRead do
begin
Packet := DecodePacket(InBufPtr, J);
K := 0;
while J > 0 do
begin
OutBufPtr^ := Char(Packet.a[K]);
Inc(OutBufPtr);
Dec(J);
Inc(K);
end;
Inc(InBufPtr, 4);
Inc(I, 4);
end;
Output.Write(OutBuf, OutBufPtr - PChar(@OutBuf));
until BytesRead = 0;
end;
function EncodeString(const Input: string): string;
var
I, K, J: Integer;
Packet: TPacket;
begin
Result := '';
I := (Length(Input) div 3) * 4;
if Length(Input) mod 3 > 0 then Inc(I, 4);
SetLength(Result, I);
J := 1;
for I := 1 to Length(Input) div 3 do
begin
Packet.i := 0;
Packet.a[0] := Byte(Input[(I - 1) * 3 + 1]);
Packet.a[1] := Byte(Input[(I - 1) * 3 + 2]);
Packet.a[2] := Byte(Input[(I - 1) * 3 + 3]);
EncodePacket(Packet, 3, PChar(@Result[J]));
Inc(J, 4);
end;
K := 0;
Packet.i := 0;
for I := Length(Input) - (Length(Input) mod 3) + 1 to Length(Input) do
begin
Packet.a[K] := Byte(Input[I]);
Inc(K);
if I = Length(Input) then
EncodePacket(Packet, Length(Input) mod 3, PChar(@Result[J]));
end;
end;
function DecodeString(const Input: string): string;
var
I, J, K: Integer;
Packet: TPacket;
begin
Result := '';
for I := 1 to Length(Input) div 4 do
begin
Packet := DecodePacket(PChar(@Input[(I - 1) * 4 + 1]), J);
K := 0;
while J > 0 do
begin
Result := Result + Packet.c[K];
Inc(K);
Dec(J);
end;
end;
end;
function UnMimeCode(MimeString : string) : string;
function UnQPCode(QPString : string) : string;
function UnHZCode(HZString : string) : string;
implementation
function Dec2Bin(Value : integer; MaxBit : integer) : string;
begin
Result := '';
while (Value > 0) do
begin
if (Trunc(Value / 2) * 2 = Value) then
Result := '0' + Result
else
Result := '1' + Result;
Value := Trunc(Value / 2);
end;
while (Length(Result) < MaxBit) do Result := '0' + Result; //填满MaxBit位
end;
function Bin2Dec(Value : string) : integer;
var
nIndex, nLength : integer;
begin
Result := 0;
nLength := Length(Value);
for nIndex := 0 to nLength - 1 do
if (Value[nLength - nIndex] = '1') then
inc(Result, Trunc(Power(2, nIndex)));
end;
function Hex2Dec(Value : string) : integer;
var
nIndex, nLength : integer;
c : char;
begin
Result := 0;
nLength := Length(Value);
for nIndex := 0 to nLength - 1 do
begin
c := Value[nLength - nIndex];
if ((c >= 'A') and (c <= 'F')) then
inc(Result, (ord(c) - 55) * Trunc(Power(16, nIndex)))
else if ((c >= '0') and (c <= '9')) then
inc(Result, (ord(c) - 48) * Trunc(Power(16, nIndex)));
end;
end;
function UnMimeCode(MimeString : string) : string;
const
c_strBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; //Base64字符集
var
strBin : string;
nIndex : integer;
i : integer;
begin
Result := '';
strBin := '';
//查找Base64字符,并转换为二进制
for nIndex := 1 to Length(MimeString) do
begin
i := Pos(MimeString[nIndex], c_strBase64);
if (i > 0) then
strBin := strBin + Dec2Bin(i - 1, 6) //填满6位,满足Base64编码原则
else if (MimeString[nIndex] = '=') then //无输入字符时候,使用等号输出(这样的写法应该是错误的,但目前想不出好的写法)
strBin := strBin + '000000';
end;
//转换为8位长的字符
for nIndex := 1 to Trunc(Length(strBin) / 8) do
begin
Result := Result + Chr(Bin2Dec(Copy(strBin, (nIndex - 1) * 8 + 1, 8)));
end;
end;
function UnQPCode(QPString : string) : string;
var
nIndex, nLength : integer;
begin
Result := '';
nIndex := 1;
nLength := Length(QPString);
while (nIndex <= nLength) do
begin
if (QPString[nIndex] = '=') and
(nIndex + 2 <= nLength) and
(((QPString[nIndex + 1] >= 'A') and (QPString[nIndex + 1] <= 'F')) or ((QPString[nIndex + 1] >= '0') and (QPString[nIndex + 1] <= '9'))) and
(((QPString[nIndex + 2] >= 'A') and (QPString[nIndex + 2] <= 'F')) or ((QPString[nIndex + 2] >= '0') and (QPString[nIndex + 2] <= '9'))) then
begin
Result := Result + Chr(Hex2Dec(Copy(QPString, nIndex + 1, 2)));
inc(nIndex, 3);
end
else
begin
Result := Result + QPString[nIndex];
inc(nIndex);
end;
end;
end;
function UnHZCode(HZString : string) : string;
var
nBeginIndex, nEndIndex : integer;
s, s1, strBin : string;
nIndex : integer;
begin
Result := HZString;
while ((nBeginIndex > 0) and (nBeginIndex < nEndIndex)) do
begin
s := Copy(Result, nBeginIndex + 2, nEndIndex - nBeginIndex - 2);
s1 := '';
for nIndex := 1 to Length(s) do
begin
if (ord(s[nIndex]) <= 127) then
begin
strBin := Dec2Bin(ord(s[nIndex]), 8); //填满8位,满足HZ编码原则
strBin[1] := '1'; //最高位置1
s1 := s1 + Chr(Bin2Dec(strBin));
end;
end;