Code: Select all
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
DataSection
Base64EncoderTable:
Data.a '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'
Data.a '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'
Data.a '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
Base64DecoderTable:
Data.b 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5
Data.b 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28
Data.b 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
EndDataSection
Procedure.s Base64Encoder_(*InBuffer.Ascii, InBufferSize.i, Flags.i=0)
Protected i.i, v.i, *InBufferEnd, PaddBytes.i, Base64$, PartBase64$, *Base64, *Base64Ptr.Ascii, *TablePtr.Ascii
If *InBuffer
*InBufferEnd = *InBuffer + InBufferSize
*Base64 = AllocateMemory(InBufferSize * 1.4, #PB_Memory_NoClear)
If *Base64
*Base64Ptr = *Base64
While *InBuffer < *InBufferEnd
v = *InBuffer\a
v << 8
*InBuffer + 1
If *InBuffer < *InBufferEnd
v | *InBuffer\a
*InBuffer + 1
Else
PaddBytes + 1
EndIf
v << 8
If *InBuffer < *InBufferEnd
v | *InBuffer\a
*InBuffer + 1
Else
PaddBytes + 1
EndIf
*TablePtr = ?Base64EncoderTable + (v >> 18) & $3F
*Base64Ptr\a = *TablePtr\a
*Base64Ptr + 1
*TablePtr = ?Base64EncoderTable + (v >> 12) & $3F
*Base64Ptr\a = *TablePtr\a
*Base64Ptr + 1
If PaddBytes < 2
*TablePtr = ?Base64EncoderTable + (v >> 6) & $3F
*Base64Ptr\a = *TablePtr\a
*Base64Ptr + 1
EndIf
If PaddBytes < 1
*TablePtr = ?Base64EncoderTable + v & $3F
*Base64Ptr\a = *TablePtr\a
*Base64Ptr + 1
EndIf
Wend
*Base64Ptr\a = 0
Base64$ = PeekS(*Base64, *Base64Ptr - *Base64, #PB_Ascii)
FreeMemory(*Base64)
EndIf
If Flags & #PB_Cipher_URL
Base64$ = ReplaceString(Base64$, "+", "-")
Base64$ = ReplaceString(Base64$, "/", "_")
EndIf
If (Flags & #PB_Cipher_NoPadding) = 0
For i = 1 To PaddBytes
If Flags & #PB_Cipher_URL
Base64$ + "%3d"
Else
Base64$ + "="
EndIf
Next i
EndIf
EndIf
ProcedureReturn Base64$
EndProcedure
Procedure.i Base64Decoder_(*Base64.Character, Flags.i=0)
Protected RealBase64$, *OutBuffer, *OutBufferTmp.Ascii, v.i, CharCounter, PaddBytes.i, *Base64Tmp.Character, Base64Size.i, Base64Char.i
*Base64Tmp = *Base64
While *Base64Tmp\c
*Base64Tmp + SizeOf(Character)
Wend
Base64Size = *Base64Tmp - *Base64
If SizeOf(Character) = 2
Base64Size / 2
EndIf
*OutBuffer = AllocateMemory(Base64Size * 0.8)
If *OutBuffer
*OutBufferTmp = *OutBuffer
*Base64Tmp = *Base64
While *Base64Tmp\c
Base64Char = *Base64Tmp\c
If Flags & #PB_Cipher_URL
If Base64Char = '_' : Base64Char = '/' : EndIf
If Base64Char = '-' : Base64Char = '+' : EndIf
If Base64Char = '%'
Base64Char = '='
*Base64Tmp + 2 * SizeOf(Character)
EndIf
EndIf
If Base64Char = '+' Or (Base64Char >= '/' And Base64Char <= '9') Or (Base64Char >= 'A' And Base64Char <= 'Z') Or (Base64Char >= 'a' And Base64Char <= 'z') Or Base64Char = '='
Select CharCounter
Case 0
v = PeekA(?Base64DecoderTable + Base64Char - 43)
CharCounter + 1
Case 1
v << 6
v | PeekA(?Base64DecoderTable + Base64Char - 43)
CharCounter + 1
Case 2
v << 6
If Base64Char <> '='
v | PeekA(?Base64DecoderTable + Base64Char - 43)
Else
PaddBytes + 1
EndIf
CharCounter + 1
Case 3
v << 6
If Base64Char <> '='
v | PeekA(?Base64DecoderTable + Base64Char - 43)
Else
PaddBytes + 1
EndIf
*OutBufferTmp\a = (v >> 16) & $FF
*OutBufferTmp + 1
If PaddBytes < 2
*OutBufferTmp\a = (v >> 8) & $FF
*OutBufferTmp + 1
EndIf
If PaddBytes < 1
*OutBufferTmp\a = v & $FF
*OutBufferTmp + 1
EndIf
CharCounter = 0
EndSelect
EndIf
*Base64Tmp + SizeOf(Character)
Wend
If CharCounter
If CharCounter = 3
v << 6
*OutBufferTmp\a = (v >> 16) & $FF
*OutBufferTmp + 1
*OutBufferTmp\a = (v >> 8) & $FF
*OutBufferTmp + 1
EndIf
If CharCounter = 2
v << 12
*OutBufferTmp\a = (v >> 16) & $FF
*OutBufferTmp + 1
EndIf
EndIf
*OutBuffer = ReAllocateMemory(*OutBuffer, *OutBufferTmp - *OutBuffer)
EndIf
ProcedureReturn *OutBuffer
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define *Buffer, Encoded$
*Buffer = UTF8("This is a test string!")
If *Buffer
Encoded$ = Base64Encoder_(*Buffer, MemorySize(*Buffer) - 1, #PB_Cipher_URL);|#PB_Cipher_NoPadding)
Debug Encoded$
FreeMemory(*Buffer)
*Buffer = Base64Decoder_(@Encoded$, #PB_Cipher_URL);|#PB_Cipher_NoPadding)
If *Buffer
Debug PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8)
FreeMemory(*Buffer)
EndIf
EndIf
CompilerEndIf