我正在寻找一种简单的方法,不需要使用像Indy这样的东西来解码包含来自Thunderbird的消息的Base64。
示例:
WW91ciBtZXNzYWdlDQoNCiAgVG86ICAgICAgeHh4QHh4eC5jb20NCiAgU3ViamVjdDogSXh4eA0KICBTZW50OiAgICBUaHUsIDIyIE9jdCAyMDA5IDAxOjE0OjM0IC0wNDAwDQoNCmRpZCBub3QgcmVhY2ggdGhlIGZvbGxvd2luZyByZWNpcGllbnQocyk6DQoNCnh4eEBneHh4IG9uIFR1ZSwgMjcgT2N0IDIwMDkgMDE6NDA6NDQgLTA0MDANCiAgICBUaGUgZS1tYWlsIHN5c3RlbSB3YXMgdW5hYmxlIHRvIGRlbGl2ZXIgdGhlIG1lc3NhZ2UsIGJ1dCBkaWQgbm90DQpyZXBvcnQgYSBzcGVjaWZpYyByZWFzb24uICBDaGVjayB0aGUgYWRkcmVzcyBhbmQgdHJ5IGFnYWluLiAgSWYgaXQgc3RpbGwNCmZhaWxzLCBjb250YWN0IHlvdXIgc3lzdGVtIGFkbWluaXN0cmF0b3IuDQogICAgPCBDaW54eHguY29tICM1LjAuMCBzbXRwOyA1LjQuNyAtIERlbGl2ZXJ5IGV4cGlyZWQNCihtZXNzYWdlIHRvbyBvbGQpICd0aW1lb3V0JyAoZGVsaXZlcnkgYXR0ZW1wdHM6IDApPg==
变为: 您的留言
To: xxx@xxx.com
Subject: Ixxx
Sent: Thu, 22 Oct 2009 01:14:34 -0400
did not reach the following recipient(s):
xxx@gxxx on Tue, 27 Oct 2009 01:40:44 -0400
The e-mail system was unable to deliver the message, but did not
report a specific reason. Check the address and try again. If it still
fails, contact your system administrator.
< Cinxxx.com #5.0.0 smtp; 5.4.7 - Delivery expired
(message too old) 'timeout' (delivery attempts: 0)>
编辑:似乎MIME Base64行的最大长度可以是76.我必须解码每个76位长的行,而不是一次解码整个消息。感谢。
答案 0 :(得分:8)
自Delphi 6以来,Delphi已包含EncdDecd
单元,其中包含DecodeString函数,该函数将包含Input
文本的base64
字符串解码为Result
带有实际解码数据的字符串(可能是二进制):
function DecodeString(const Input: string): string;
自Delphi 2009以来,它还包含DecodeBase64函数,该函数将Input
AnsiString解码为TBytes的二进制Result
:
function DecodeBase64(const Input: AnsiString): TBytes;
除了我给出的earlier Delphi/PHP base64 answer之外,我现在写了一个小单元测试,显示了DecodeString和EncodeString的工作原理:
unit Base64TestCaseUnit;
interface
uses
Classes, SysUtils, TestFrameWork, Generics.Collections;
{
base64 test vectors: http://tools.ietf.org/html/rfc4648
BASE64("") = ""
BASE64("f") = "Zg=="
BASE64("fo") = "Zm8="
BASE64("foo") = "Zm9v"
BASE64("foob") = "Zm9vYg=="
BASE64("fooba") = "Zm9vYmE="
BASE64("foobar") = "Zm9vYmFy"
}
const
Key_ = '';
Value_ = '';
Key_f = 'f';
Value_f = 'Zg==';
Key_fo = 'fo';
Value_fo = 'Zm8=';
Key_foo = 'foo';
Value_foo = 'Zm9v';
Key_foob = 'foob';
Value_foob = 'Zm9vYg==';
Key_fooba = 'fooba';
Value_fooba = 'Zm9vYmE=';
Key_foobar = 'foobar';
Value_foobar = 'Zm9vYmFy';
// binary test vector
Key_binary = #1#2#3#4;
Value_binary = 'AQIDBA==';
type
TStringStringDictionary = TDictionary<string, string>;
TBase64TestCase = class(TTestCase)
strict private
FBase64VectorsDictionary: TStringStringDictionary;
strict protected
procedure DecodeTestOneKey(const ExpectedKey: string); virtual;
procedure EncodeTestOneKey(const ActualKey: string); virtual;
property Base64VectorsDictionary: TStringStringDictionary read FBase64VectorsDictionary;
protected
procedure SetUp; override;
procedure TearDown; override;
published
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_binary;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_f;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_fo;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_foo;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_foob;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_fooba;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_DecodeString_Test_foobar;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_binary;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_f;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_fo;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_foo;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_foob;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_fooba;
{$IFDEF CLR}[Test]{$ENDIF}
procedure Base64_EncodeString_Test_foobar;
end;
implementation
uses
EncdDecd;
procedure TBase64TestCase.Base64_DecodeString_Test_;
begin
DecodeTestOneKey(Key_);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_binary;
begin
DecodeTestOneKey(Key_binary);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_f;
begin
DecodeTestOneKey(Key_f);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_fo;
begin
DecodeTestOneKey(Key_fo);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_foo;
begin
DecodeTestOneKey(Key_foo);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_foob;
begin
DecodeTestOneKey(Key_foob);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_fooba;
begin
DecodeTestOneKey(Key_fooba);
end;
procedure TBase64TestCase.Base64_DecodeString_Test_foobar;
begin
DecodeTestOneKey(Key_foobar);
end;
procedure TBase64TestCase.SetUp;
begin
FBase64VectorsDictionary := TStringStringDictionary.Create();
FBase64VectorsDictionary.Add(Key_, Value_);
FBase64VectorsDictionary.Add(Key_f, Value_f);
FBase64VectorsDictionary.Add(Key_fo, Value_fo);
FBase64VectorsDictionary.Add(Key_foo, Value_foo);
FBase64VectorsDictionary.Add(Key_foob, Value_foob);
FBase64VectorsDictionary.Add(Key_fooba, Value_fooba);
FBase64VectorsDictionary.Add(Key_foobar, Value_foobar);
FBase64VectorsDictionary.Add(Key_binary, Value_binary);
end;
procedure TBase64TestCase.TearDown;
begin
FBase64VectorsDictionary.Free();
FBase64VectorsDictionary := nil;
end;
procedure TBase64TestCase.Base64_EncodeString_Test_;
begin
EncodeTestOneKey(Key_);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_binary;
begin
EncodeTestOneKey(Key_binary);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_f;
begin
EncodeTestOneKey(Key_f);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_fo;
begin
EncodeTestOneKey(Key_fo);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_foo;
begin
EncodeTestOneKey(Key_foo);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_foob;
begin
EncodeTestOneKey(Key_foob);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_fooba;
begin
EncodeTestOneKey(Key_fooba);
end;
procedure TBase64TestCase.Base64_EncodeString_Test_foobar;
begin
EncodeTestOneKey(Key_foobar);
end;
procedure TBase64TestCase.DecodeTestOneKey(const ExpectedKey: string);
var
ActualKey: string;
ExpectedValue: string;
begin
ExpectedValue := FBase64VectorsDictionary[ExpectedKey];
ActualKey := DecodeString(ExpectedValue);
Self.CheckEquals(ExpectedKey, ActualKey, Format('base64 decode of "%s" should be "%s"', [ExpectedValue, ExpectedKey]));
end;
procedure TBase64TestCase.EncodeTestOneKey(const ActualKey: string);
var
ActualValue: string;
ExpectedValue: string;
begin
ExpectedValue := FBase64VectorsDictionary[ActualKey];
ActualValue := EncodeString(ActualKey);
Self.CheckEquals(ExpectedValue, ActualValue, Format('base64 of "%s" should be "%s"', [ActualKey, ExpectedValue]));
end;
initialization
RegisterTest('', TBase64TestCase.Suite);
end.
答案 1 :(得分:5)
解码并不难编码,但这里有一个博客,里面有一些Delphi的示例代码
http://www.delphifaq.net/how-to-base-64-mime-encode-and-decode-a-string/
基本思想是有64个字符,每个字符代表6位的位模式。用表查找将字符转回6位,然后取出你的位列表,然后将它们分成8位块来制作字节。
答案 2 :(得分:1)
uses
Math;
var
Base64: array[0..63] of AnsiChar = (
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/');
function IndexOfBase64(const C: AnsiChar): Integer;
begin
for Result := Low(Base64) to High(Base64) do
if Base64[Result] = C then
EXIT;
Result := -1;
end;
function DecodeBase64(Value: AnsiString): AnsiString;
var
iC, iB: Integer;
B: array of Integer;
C: array[0..3] of Integer;
begin
SetLength(B, Floor(Length(Value) / 4) * 3);
iC := 1;
iB := 0;
while iC <= (Length(Value) - 3) do
begin
C[0] := IndexOfBase64(Value[iC]);
C[1] := IndexOfBase64(Value[iC + 1]);
C[2] := IndexOfBase64(Value[iC + 2]);
C[3] := IndexOfBase64(Value[iC + 3]);
B[iB] := (C[0] shl 2) or (C[1] shr 4);
B[iB + 1] := ((C[1] and 15) shl 4) or (C[2] shr 2);
B[iB + 2] := ((C[2] and 3) shl 6) or C[3];
Inc(iC, 4);
Inc(iB, 3);
end;
SetLength(B, Length(B) - (Length(B) mod 16));
for iB := 0 to High(B) do
Result := Result + Chr(B[iB]);
end;
答案 3 :(得分:0)
如果您只想要一个现成的解决方案,请尝试DIMime