decoder
alarming
autosfx
aysalia
calllib
checksum-tools
colormanager
cryptochat
currency_converter
delphiutils
distributed
dpcstudio
dpg2
fastphp
fileformats
filter_foundry
forest
gridgame
ht46f47_simulator
indexer_suite
ipe_artfile_utils
javautils
jumper
lightgame
logviewer
musikbox
mystic_house
oidconverter
oidinfo_api
oidinfo_new_design
oidplus
personal-webbase
php_antispam
php_clientchallenge
php_guestbook
php_utils
plumbers
prepend
recyclebinunit
simple_log_event
sokoban
spacemission
stackman
userdetect2
uuid_mac_utils
vgwhois
vnag
webcounter
winbugtracker
yt_downloader
BlueGrey
calm
Elegant
Català-Valencià – Catalan
中文 – Chinese (Simplified)
中文 – Chinese (Traditional)
Česky – Czech
Dansk – Danish
Nederlands – Dutch
English – English
Suomi – Finnish
Français – French
Deutsch – German
עברית – Hebrew
हिंदी – Hindi
Magyar – Hungarian
Bahasa Indonesia – Indonesian
Italiano – Italian
日本語 – Japanese
한국어 – Korean
Македонски – Macedonian
मराठी – Marathi
Norsk – Norwegian
Polski – Polish
Português – Portuguese
Português – Portuguese (Brazil)
Русский – Russian
Slovenčina – Slovak
Slovenščina – Slovenian
Español – Spanish
Svenska – Swedish
Türkçe – Turkish
Українська – Ukrainian
Oëzbekcha – Uzbek
Subversion Repositories
decoder
decoder
/
trunk
/
INCLUDES
/
base64.pas
– Rev 2
Rev
Go to most recent revision
|
Blame
|
Compare with Previous
|
Last modification
|
View Log
|
RSS feed
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Unit Name : uBase64Codec
* Author : Daniel Wischnewski
* Copyright : Copyright © 2001-2003 by gate(n)etwork GmbH. All Rights Reserved.
* Creator : Daniel Wischnewski
* Contact : Daniel Wischnewski (e-mail: delphi3000(at)wischnewski.tv);
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
// * * * License * * *
//
// The contents of this file are used with permission, subject to the Mozilla
// Public License Version 1.1 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://www.mozilla.org/MPL/MPL-1.1.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
// the specific language governing rights and limitations under the License.
//
// * * * My Wish * * *
//
// If you come to use this unit for your work, I would like to know about it.
// Drop me an e-mail and let me know how it worked out for you. If you wish, you
// can send me a copy of your work. No obligations!
// My e-mail address: delphi3000(at)wischnewski.tv
//
// * * * History * * *
//
// Version 1.0 (Oct-10 2002)
// first published on Delphi-PRAXiS (www.delphipraxis.net)
//
// Version 1.1 (May-13 2003)
// introduced a compiler switch (SpeedDecode) to switch between a faster
// decoding variant (prior version) and a litte less fast, but secure variant
// to work around bad formatted data (decoding only!)
//
// Version 1.2 (Juni-09 2004)
// included compiler switch {$0+}. In Delphi 6 and 7 projects using this code
// with compiler optimizations turned off will raise an access violation
// {$O+} will ensure that this unit runs with compiler optimizations.
// This option does *not* influence other parts of the project including this
// unit.
// Thanks to Ralf Manschewski for pointing out this problem.
//
unit
Base64
;
{$O+}
interface
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !! THE COMPILER SWITCH MAY BE USED TO ADJUST THE BEHAVIOR !!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// enable "SpeedDecode"
// the switch to gain speed while decoding the message, however, the codec
// will raise different exceptions/access violations or invalid output if
// the incoming data is invalid or missized.
// disable "SpeedDecode"
// the switch to enable a data check, that will scan the data to decode to
// be valid. This method is to be used if you cannot guarantee to validity
// of the data to be decoded.
{.DEFINE SpeedDecode}
{$IFNDEF SpeedDecode}
{$DEFINE ValidityCheck}
{$ENDIF}
uses
SysUtils
;
// codiert einen String in die zugehörige Base64-Darstellung
function
Base64Encode
(
const
InText
:
AnsiString
)
:
AnsiString
;
overload
;
// decodiert die Base64-Darstellung eines Strings in den zugehörigen String
function
Base64Decode
(
const
InText
:
AnsiString
)
:
AnsiString
;
overload
;
// bestimmt die Größe der Base64-Darstellung
function
CalcEncodedSize
(
InSize
:
Cardinal
)
:
Cardinal
;
// bestimmt die Größe der binären Darstellung
function
CalcDecodedSize
(
const
InBuffer
;
InSize
:
Cardinal
)
:
Cardinal
;
// codiert einen Buffer in die zugehörige Base64-Darstellung
procedure
Base64Encode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
;
overload
;
register
;
// decodiert die Base64-Darstellung in einen Buffer
{$IFDEF SpeedDecode}
procedure
Base64Decode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
;
overload
;
register
;
{$ENDIF}
{$IFDEF ValidityCheck}
function
Base64Decode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
:
Boolean
;
overload
;
register
;
{$ENDIF}
// codiert einen String in die zugehörige Base64-Darstellung
procedure
Base64Encode
(
const
InText
:
PAnsiChar
;
var
OutText
:
PAnsiChar
)
;
overload
;
// decodiert die Base64-Darstellung eines Strings in den zugehörigen String
procedure
Base64Decode
(
const
InText
:
PAnsiChar
;
var
OutText
:
PAnsiChar
)
;
overload
;
// codiert einen String in die zugehörige Base64-Darstellung
procedure
Base64Encode
(
const
InText
:
AnsiString
;
var
OutText
:
AnsiString
)
;
overload
;
// decodiert die Base64-Darstellung eines Strings in den zugehörigen String
procedure
Base64Decode
(
const
InText
:
AnsiString
;
var
OutText
:
AnsiString
)
;
overload
;
implementation
const
cBase64Codec
:
array
[
0
..
63
]
of
AnsiChar
=
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
;
Base64Filler
=
'='
;
function
Base64Encode
(
const
InText
:
string
)
:
string
;
overload
;
begin
Base64Encode
(
InText
,
Result
)
;
end
;
function
Base64Decode
(
const
InText
:
string
)
:
string
;
overload
;
begin
Base64Decode
(
InText
,
Result
)
;
end
;
function
CalcEncodedSize
(
InSize
:
Cardinal
)
:
Cardinal
;
begin
// no buffers passed along, calculate outbuffer size needed
Result
:
=
(
InSize
div
3
)
shl
2
;
if
(
(
InSize
mod
3
)
>
0
)
then
Inc
(
Result
,
4
)
;
end
;
function
CalcDecodedSize
(
const
InBuffer
;
InSize
:
Cardinal
)
:
Cardinal
;
type
BA
=
array
of
Byte
;
begin
Result
:
=
0
;
if
InSize
=
0
then
Exit
;
if
InSize
mod
4
<>
0
then
Exit
;
Result
:
=
InSize
div
4
*
3
;
if
(
BA
(
InBuffer
)
[
InSize
-
2
]
=
Ord
(
Base64Filler
)
)
then
Dec
(
Result
,
2
)
else
if
BA
(
InBuffer
)
[
InSize
-
1
]
=
Ord
(
Base64Filler
)
then
Dec
(
Result
)
;
end
;
procedure
Base64Encode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
;
register
;
var
ByThrees
,
LeftOver
:
Cardinal
;
// reset in- and outbytes positions
asm
// load addresses for source and destination
// PBYTE(InBuffer);
mov ESI
,
[
EAX
]
// PBYTE(OutBuffer);
mov EDI
,
[
ECX
]
// ByThrees := InSize div 3;
// LeftOver := InSize mod 3;
// load InSize (stored in EBX)
mov EAX
,
EBX
// load 3
mov ECX
,
$03
// clear upper 32 bits
xor
EDX
,
EDX
// divide by ECX
div
ECX
// save result
mov ByThrees
,
EAX
// save remainder
mov LeftOver
,
EDX
// load addresses
lea ECX
,
cBase64Codec
[
0
]
// while I < ByThrees do
// begin
xor
EAX
,
EAX
xor
EBX
,
EBX
xor
EDX
,
EDX
cmp ByThrees
,
0
jz
@@
LeftOver
@@
LoopStart
:
// load the first two bytes of the source triplet
LODSW
// write Bits 0..5 to destination
mov BL
,
AL
shr
BL
,
2
mov DL
,
BYTE
PTR
[
ECX
+
EBX
]
// save the Bits 12..15 for later use [1]
mov BH
,
AH
and
BH
,
$0F
// save Bits 6..11
rol AX
,
4
and
AX
,
$3F
mov DH
,
BYTE
PTR
[
ECX
+
EAX
]
mov AX
,
DX
// store the first two bytes of the destination quadruple
STOSW
// laod last byte (Bits 16..23) of the source triplet
LODSB
// extend bits 12..15 [1] with Bits 16..17 and save them
mov BL
,
AL
shr
BX
,
6
mov DL
,
BYTE
PTR
[
ECX
+
EBX
]
// save bits 18..23
and
AL
,
$3F
xor
AH
,
AH
mov DH
,
BYTE
PTR
[
ECX
+
EAX
]
mov AX
,
DX
// store the last two bytes of the destination quadruple
STOSW
dec ByThrees
jnz
@@
LoopStart
@@
LeftOver
:
// there are up to two more bytes to encode
cmp LeftOver
,
0
jz
@@
Done
// clear result
xor
EAX
,
EAX
xor
EBX
,
EBX
xor
EDX
,
EDX
// get left over 1
LODSB
// load the first six bits
shl
AX
,
6
mov BL
,
AH
// save them
mov DL
,
BYTE
PTR
[
ECX
+
EBX
]
// another byte ?
dec LeftOver
jz
@@
SaveOne
// save remaining two bits
shl
AX
,
2
and
AH
,
$03
// get left over 2
LODSB
// load next 4 bits
shl
AX
,
4
mov BL
,
AH
// save all 6 bits
mov DH
,
BYTE
PTR
[
ECX
+
EBX
]
shl
EDX
,
16
// save last 4 bits
shr
AL
,
2
mov BL
,
AL
// save them
mov DL
,
BYTE
PTR
[
ECX
+
EBX
]
// load base 64 'no more data flag'
mov DH
,
Base64Filler
jmp
@@
WriteLast4
@@
SaveOne
:
// adjust the last two bits
shr
AL
,
2
mov BL
,
AL
// save them
mov DH
,
BYTE
PTR
[
ECX
+
EBX
]
shl
EDX
,
16
// load base 64 'no more data flags'
mov DH
,
Base64Filler
mov DL
,
Base64Filler
// ignore jump, as jump reference is next line !
// jmp @@WriteLast4
@@
WriteLast4
:
// load and adjust result
mov EAX
,
EDX
ror EAX
,
16
// save it to destination
STOSD
@@
Done
:
end
;
{$IFDEF SpeedDecode}
procedure
Base64Decode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
;
overload
;
register
;
{$ENDIF}
{$IFDEF ValidityCheck}
function
Base64Decode
(
const
InBuffer
;
InSize
:
Cardinal
;
var
OutBuffer
)
:
Boolean
;
overload
;
register
;
{$ENDIF}
const
{$IFDEF SpeedDecode}
cBase64Codec
:
array
[
0
..
127
]
of
Byte
=
{$ENDIF}
{$IFDEF ValidityCheck}
cBase64Codec
:
array
[
0
..
255
]
of
Byte
=
{$ENDIF}
(
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{005>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 000..009
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{015>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 010..019
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{025>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 020..029
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{035>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 030..039
$FF
,
$FF
,
$FF
,
$3E
,
$FF
,
{045>}
$FF
,
$FF
,
$3F
,
$34
,
$35
,
// 040..049
$36
,
$37
,
$38
,
$39
,
$3A
,
{055>}
$3B
,
$3C
,
$3D
,
$FF
,
$FF
,
// 050..059
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{065>}
$00
,
$01
,
$02
,
$03
,
$04
,
// 060..069
$05
,
$06
,
$07
,
$08
,
$09
,
{075>}
$0A
,
$0B
,
$0C
,
$0D
,
$0E
,
// 070..079
$0F
,
$10
,
$11
,
$12
,
$13
,
{085>}
$14
,
$15
,
$16
,
$17
,
$18
,
// 080..089
$19
,
$FF
,
$FF
,
$FF
,
$FF
,
{095>}
$FF
,
$FF
,
$1A
,
$1B
,
$1C
,
// 090..099
$1D
,
$1E
,
$1F
,
$20
,
$21
,
{105>}
$22
,
$23
,
$24
,
$25
,
$26
,
// 100..109
$27
,
$28
,
$29
,
$2A
,
$2B
,
{115>}
$2C
,
$2D
,
$2E
,
$2F
,
$30
,
// 110..119
$31
,
$32
,
$33
,
$FF
,
$FF
,
{125>}
$FF
,
$FF
,
$FF
// 120..127
{$IFDEF ValidityCheck}
{125>}
,
$FF
,
$FF
,
// 128..129
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{135>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 130..139
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{145>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 140..149
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{155>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 150..159
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{165>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 160..169
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{175>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 170..179
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{185>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 180..189
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{195>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 190..199
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{205>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 200..209
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{215>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 210..219
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{225>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 220..229
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{235>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 230..239
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{245>}
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
// 240..249
$FF
,
$FF
,
$FF
,
$FF
,
$FF
,
{255>}
$FF
// 250..255
{$ENDIF}
)
;
asm
push EBX
mov ESI
,
[
EAX
]
mov EDI
,
[
ECX
]
{$IFDEF ValidityCheck}
mov EAX
,
InSize
and
EAX
,
$03
cmp EAX
,
$00
jz
@@
DecodeStart
jmp
@@
ErrorDone
@@
DecodeStart
:
{$ENDIF}
mov EAX
,
InSize
shr
EAX
,
2
jz
@@
Done
lea ECX
,
cBase64Codec
[
0
]
xor
EBX
,
EBX
dec EAX
jz
@@
LeftOver
push EBP
mov EBP
,
EAX
@@
LoopStart
:
// load four bytes into EAX
LODSD
// save them to EDX as AX is used to store results
mov EDX
,
EAX
// get bits 0..5
mov BL
,
DL
// decode
mov AH
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AH
,
$FF
jz
@@
ErrorDoneAndPopEBP
{$ENDIF}
// get bits 6..11
mov BL
,
DH
// decode
mov AL
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AL
,
$FF
jz
@@
ErrorDoneAndPopEBP
{$ENDIF}
// align last 6 bits
shl
AL
,
2
// get first 8 bits
ror AX
,
6
// store first byte
STOSB
// align remaining 4 bits
shr
AX
,
12
// get next two bytes from source quad
shr
EDX
,
16
// load bits 12..17
mov BL
,
DL
// decode
mov AH
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AH
,
$FF
jz
@@
ErrorDoneAndPopEBP
{$ENDIF}
// align ...
shl
AH
,
2
// ... and adjust
rol AX
,
4
// get last bits 18..23
mov BL
,
DH
// decord
mov BL
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp BL
,
$FF
jz
@@
ErrorDoneAndPopEBP
{$ENDIF}
// enter in destination word
or
AH
,
BL
// and store to destination
STOSW
// more coming ?
dec EBP
jnz
@@
LoopStart
pop EBP
// no
// last four bytes are handled separately, as special checking is needed
// on the last two bytes (may be end of data signals '=' or '==')
@@
LeftOver
:
// get the last four bytes
LODSD
// save them to EDX as AX is used to store results
mov EDX
,
EAX
// get bits 0..5
mov BL
,
DL
// decode
mov AH
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AH
,
$FF
jz
@@
ErrorDone
{$ENDIF}
// get bits 6..11
mov BL
,
DH
// decode
mov AL
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AL
,
$FF
jz
@@
ErrorDone
{$ENDIF}
// align last 6 bits
shl
AL
,
2
// get first 8 bits
ror AX
,
6
// store first byte
STOSB
// get next two bytes from source quad
shr
EDX
,
16
// check DL for "end of data signal"
cmp DL
,
Base64Filler
jz
@@
SuccessDone
// align remaining 4 bits
shr
AX
,
12
// load bits 12..17
mov BL
,
DL
// decode
mov AH
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp AH
,
$FF
jz
@@
ErrorDone
{$ENDIF}
// align ...
shl
AH
,
2
// ... and adjust
rol AX
,
4
// store second byte
STOSB
// check DH for "end of data signal"
cmp DH
,
Base64Filler
jz
@@
SuccessDone
// get last bits 18..23
mov BL
,
DH
// decord
mov BL
,
BYTE
PTR
[
ECX
+
EBX
]
{$IFDEF ValidityCheck}
// check valid code
cmp BL
,
$FF
jz
@@
ErrorDone
{$ENDIF}
// enter in destination word
or
AH
,
BL
// AH - AL for saving last byte
mov AL
,
AH
// store third byte
STOSB
@@
SuccessDone
:
{$IFDEF ValidityCheck}
mov Result
,
$01
jmp
@@
Done
@@
ErrorDoneAndPopEBP
:
pop EBP
@@
ErrorDone
:
mov Result
,
$00
{$ENDIF}
@@
Done
:
pop EBX
end
;
procedure
Base64Encode
(
const
InText
:
PAnsiChar
;
var
OutText
:
PAnsiChar
)
;
var
InSize
,
OutSize
:
Cardinal
;
begin
// get size of source
InSize
:
=
Length
(
InText
)
;
// calculate size for destination
OutSize
:
=
CalcEncodedSize
(
InSize
)
;
// reserve memory
OutText
:
=
StrAlloc
(
Succ
(
OutSize
)
)
;
OutText
[
OutSize
]
:
=
#0
;
// encode !
Base64Encode
(
InText
,
InSize
,
OutText
)
;
end
;
procedure
Base64Encode
(
const
InText
:
AnsiString
;
var
OutText
:
AnsiString
)
;
overload
;
var
InSize
,
OutSize
:
Cardinal
;
PIn
,
POut
:
Pointer
;
begin
// get size of source
InSize
:
=
Length
(
InText
)
;
// calculate size for destination
OutSize
:
=
CalcEncodedSize
(
InSize
)
;
// prepare string length to fit result data
SetLength
(
OutText
,
OutSize
)
;
PIn
:
=
@
InText
[
1
]
;
POut
:
=
@
OutText
[
1
]
;
// encode !
Base64Encode
(
PIn
,
InSize
,
POut
)
;
end
;
procedure
Base64Decode
(
const
InText
:
PAnsiChar
;
var
OutText
:
PAnsiChar
)
;
overload
;
var
InSize
,
OutSize
:
Cardinal
;
begin
// get size of source
InSize
:
=
Length
(
InText
)
;
// calculate size for destination
OutSize
:
=
CalcDecodedSize
(
InText
,
InSize
)
;
// reserve memory
OutText
:
=
StrAlloc
(
Succ
(
OutSize
)
)
;
OutText
[
OutSize
]
:
=
#0
;
// encode !
{$IFDEF SpeedDecode}
Base64Decode
(
InText
,
InSize
,
OutText
)
;
{$ENDIF}
{$IFDEF ValidityCheck}
if
not
Base64Decode
(
InText
,
InSize
,
OutText
)
then
OutText
[
0
]
:
=
#0
;
{$ENDIF}
end
;
procedure
Base64Decode
(
const
InText
:
AnsiString
;
var
OutText
:
AnsiString
)
;
overload
;
var
InSize
,
OutSize
:
Cardinal
;
PIn
,
POut
:
Pointer
;
begin
// get size of source
InSize
:
=
Length
(
InText
)
;
// calculate size for destination
PIn
:
=
@
InText
[
1
]
;
OutSize
:
=
CalcDecodedSize
(
PIn
,
InSize
)
;
// prepare string length to fit result data
SetLength
(
OutText
,
OutSize
)
;
FillChar
(
OutText
[
1
]
,
OutSize
,
'.'
)
;
POut
:
=
@
OutText
[
1
]
;
// encode !
{$IFDEF SpeedDecode}
Base64Decode
(
PIn
,
InSize
,
POut
)
;
{$ENDIF}
{$IFDEF ValidityCheck}
if
not
Base64Decode
(
PIn
,
InSize
,
POut
)
then
SetLength
(
OutText
,
0
)
;
{$ENDIF}
end
;
end
.