-------------------------------------------------------------------------------- -- Title: MIMEBase64.lua -- Description: Like a square peg in a round hole -- Author: Raphaël Szwarc http://alt.textdrive.com/lua/ -- Creation Date: February 1, 2005 -- Legal: Copyright (C) 2005 Raphaël Szwarc -------------------------------------------------------------------------------- -- Based on Diego Nehab's LuaSocket 1.1 base64.lua: -- http://www.cs.princeton.edu/~diego/professional/luasocket/old/luasocket-1.1/ -- import dependencies local LUObject = require( "LUObject" ) local math = require( "math" ) local string = require( "string" ) -- define the class local super = LUObject local self = super() -- constants local ByteToChar = { [ 0 ] = "A", [ 1 ] = "B", [ 2 ] = "C", [ 3 ] = "D", [ 4 ] = "E", [ 5 ] = "F", [ 6 ] = "G", [ 7 ] = "H", [ 8 ] = "I", [ 9 ] = "J", [ 10 ] = "K", [ 11 ] = "L", [ 12 ] = "M", [ 13 ] = "N", [ 14 ] = "O", [ 15 ] = "P", [ 16 ] = "Q", [ 17 ] = "R", [ 18 ] = "S", [ 19 ] = "T", [ 20 ] = "U", [ 21 ] = "V", [ 22 ] = "W", [ 23 ] = "X", [ 24 ] = "Y", [ 25 ] = "Z", [ 26 ] = "a", [ 27 ] = "b", [ 28 ] = "c", [ 29 ] = "d", [ 30 ] = "e", [ 31 ] = "f", [ 32 ] = "g", [ 33 ] = "h", [ 34 ] = "i", [ 35 ] = "j", [ 36 ] = "k", [ 37 ] = "l", [ 38 ] = "m", [ 39 ] = "n", [ 40 ] = "o", [ 41 ] = "p", [ 42 ] = "q", [ 43 ] = "r", [ 44 ] = "s", [ 45 ] = "t", [ 46 ] = "u", [ 47 ] = "v", [ 48 ] = "w", [ 49 ] = "x", [ 50 ] = "y", [ 51 ] = "z", [ 52 ] = "0", [ 53 ] = "1", [ 54 ] = "2", [ 55 ] = "3", [ 56 ] = "4", [ 57 ] = "5", [ 58 ] = "6", [ 59 ] = "7", [ 60 ] = "8", [ 61 ] = "9", [ 62 ] = "+", [ 63 ] = "/" } local CharToByte = { [ "A" ] = 0, [ "B" ] = 1, [ "C" ] = 2, [ "D" ] = 3, [ "E" ] = 4, [ "F" ] = 5, [ "G" ] = 6, [ "H" ] = 7, [ "I" ] = 8, [ "J" ] = 9, [ "K" ] = 10, [ "L" ] = 11, [ "M" ] = 12, [ "N" ] = 13, [ "O" ] = 14, [ "P" ] = 15, [ "Q" ] = 16, [ "R" ] = 17, [ "S" ] = 18, [ "T" ] = 19, [ "U" ] = 20, [ "V" ] = 21, [ "W" ] = 22, [ "X" ] = 23, [ "Y" ] = 24, [ "Z" ] = 25, [ "a" ] = 26, [ "b" ] = 27, [ "c" ] = 28, [ "d" ] = 29, [ "e" ] = 30, [ "f" ] = 31, [ "g" ] = 32, [ "h" ] = 33, [ "i" ] = 34, [ "j" ] = 35, [ "k" ] = 36, [ "l" ] = 37, [ "m" ] = 38, [ "n" ] = 39, [ "o" ] = 40, [ "p" ] = 41, [ "q" ] = 42, [ "r" ] = 43, [ "s" ] = 44, [ "t" ] = 45, [ "u" ] = 46, [ "v" ] = 47, [ "w" ] = 48, [ "x" ] = 49, [ "y" ] = 50, [ "z" ] = 51, [ "0" ] = 52, [ "1" ] = 53, [ "2" ] = 54, [ "3" ] = 55, [ "4" ] = 56, [ "5" ] = 57, [ "6" ] = 58, [ "7" ] = 59, [ "8" ] = 60, [ "9" ] = 61, [ "+" ] = 62, [ "/" ] = 63 } -- private method to convert bytes to chars local function BytesToChars( byteA, byteB, byteC ) local aValue = byteA:byte() * 65536 + byteB:byte() * 256 + byteC:byte() local charA, charB, charC, charD charD = math.mod( aValue, 64 ) aValue = ( aValue - charD ) / 64 charC = math.mod( aValue, 64 ) aValue = ( aValue - charC ) / 64 charB = math.mod( aValue, 64 ) charA = ( aValue - charB ) / 64 return ByteToChar[ charA ] .. ByteToChar[ charB ] .. ByteToChar[ charC ] .. ByteToChar[ charD ] end -- private method to encode a given padding local function EncodePadding( aPadding ) local byteA, byteB = aPadding:match( "(.?)(.?)" ) if byteB == "" then local aValue = byteA:byte() * 16 local charA, charB charB = math.mod( aValue, 64 ) charA = ( aValue - charB ) / 64 return ByteToChar[ charA ] .. ByteToChar[ charB ] .. "==" else local aValue = byteA:byte() * 1024 + byteB:byte() * 4 local charA, charB, charC charC = math.mod( aValue, 64 ) aValue = ( aValue - charC ) / 64 charB = math.mod( aValue, 64 ) charA = ( aValue - charB ) / 64 return ByteToChar[ charA ] .. ByteToChar[ charB ] .. ByteToChar[ charC ] .. "=" end end -- method to base64 encode a given string function self:encode( aString ) if aString ~= nil then local aLength = aString:len() local aPaddingLength = math.mod( aLength, 3 ) local aValue = "" local aPadding = "" aLength = aLength - aPaddingLength if aLength > 0 then aValue = aString:sub( 1, aLength ):gsub( "(.)(.)(.)", BytesToChars ) end if aPaddingLength > 0 then aPadding = EncodePadding( aString:sub( aLength + 1 ) ) end return aValue .. aPadding end return nil end -- private method to convert chars to bytes local function CharsToBytes( charA, charB, charC, charD ) local aValue = CharToByte[ charA ] * 262144 + CharToByte[ charB ] * 4096 + CharToByte[ charC ] * 64 + CharToByte[ charD ] local byteA, byteB, byteC byteC = math.mod( aValue, 256 ) aValue = ( aValue - byteC ) / 256 byteB = math.mod( aValue, 256 ) byteA = ( aValue - byteB ) / 256 return string.char( byteA, byteB, byteC ) end -- private method to decode a given padding local function DecodePadding( aPadding ) local charA, charB, charC, charD = aPadding:match( "(.)(.)(.)(.)" ) if charD ~= "=" then return CharsToBytes( charA, charB, charC, charD ) elseif charC ~= "=" then local aValue = CharToByte[ charA ] * 1024 + CharToByte[ charB ] * 16 + CharToByte[ charC ] / 4 local byteA, byteB byteB = math.mod( aValue, 256 ) byteA = ( aValue - byteB ) / 256 return string.char( byteA, byteB ) else local aValue = CharToByte[ charA ] * 4 + CharToByte[ charB ] / 16 local byteA = math.mod( aValue, 256 ) return string.char( byteA ) end end -- method to decode a given base64 string function self:decode( aString ) if aString ~= nil then local aLength = aString:len() local aValue = "" local aPadding = "" if aLength > 4 then aValue = aString:sub( 1, -5 ):gsub( "(.)(.)(.)(.)", CharsToBytes ) end aPadding = DecodePadding( aString:sub( -4 ) ) return aValue .. aPadding end return nil end return self