GLOBAL lngTrack AS LONG
GLOBAL arrLongConversion() AS LONG
GLOBAL arrSplit64() AS BYTE
%OFFSET_4 = 4294967296
%MAXINT_4 = 2147483647
%S11 = 7
%S12 = 12
%S13 = 17
%S14 = 22
%S21 = 5
%S22 = 9
%S23 = 14
%S24 = 20
%S31 = 4
%S32 = 11
%S33 = 16
%S34 = 23
%S41 = 6
%S42 = 10
%S43 = 15
%S44 = 21
FUNCTION MD5LongConversion(dblValue AS DOUBLE) AS LONG
IF dblValue < 0 OR dblValue >= %OFFSET_4 THEN ERROR 6
IF dblValue <= %MAXINT_4 THEN
MD5LongConversion = dblValue
ELSE
MD5LongConversion = dblValue - %OFFSET_4
END IF
END FUNCTION
FUNCTION MD5LongAdd4(lngVal1 AS LONG, lngVal2 AS LONG, lngVal3 AS LONG, lngVal4 AS LONG) AS LONG
 
IM lngHighWord AS LONG
 
IM lngLowWord AS LONG
 
IM lngOverflow AS LONG
lngLowWord = (lngVal1 AND &HFFFF&
+ (lngVal2 AND &HFFFF&
+ (lngVal3 AND &HFFFF&
+ (lngVal4 AND &HFFFF&
lngOverflow = lngLowWord \ 65536
lngHighWord = (((lngVal1 AND &HFFFF0000) \ 65536) + ((lngVal2 AND &HFFFF0000) \ 65536) + ((lngVal3 AND &HFFFF0000) \ 65536) + ((lngVal4 AND &HFFFF0000) \ 65536) + lngOverflow) AND &HFFFF&
MD5LongAdd4 = MD5LongConversion((lngHighWord * 65536#) + (lngLowWord AND &HFFFF&
)
END FUNCTION
FUNCTION MD5Rotate(lngValue AS LONG, lngBits AS LONG) AS LONG
 
IM lngSign AS LONG
 
IM lngI AS LONG
lngBits = (lngBits MOD 32)
IF lngBits = 0 THEN MD5Rotate = lngValue: EXIT FUNCTION
FOR lngI = 1 TO lngBits
lngSign = lngValue AND &HC0000000
lngValue = (lngValue AND &H3FFFFFFF) * 2
'(CBYT(lngSign AND &H40000000)
lngValue = lngValue OR ((lngSign < 0) AND 1) OR (ISTRUE(lngSign AND &H40000000) AND &H80000000)
'/////////////////////
NEXT
MD5Rotate = lngValue
END FUNCTION
FUNCTION MD5LongAdd(lngVal1 AS LONG, lngVal2 AS LONG) AS LONG
 
IM lngHighWord AS LONG
 
IM lngLowWord AS LONG
 
IM lngOverflow AS LONG
lngLowWord = (lngVal1 AND &HFFFF&
+ (lngVal2 AND &HFFFF&
lngOverflow = lngLowWord \ 65536
lngHighWord = (((lngVal1 AND &HFFFF0000) \ 65536) + ((lngVal2 AND &HFFFF0000) \ 65536) + lngOverflow) AND &HFFFF&
MD5LongAdd = MD5LongConversion((lngHighWord * 65536#) + (lngLowWord AND &HFFFF&
)
END FUNCTION
FUNCTION MD5Round(strRound AS STRING, a AS LONG, b AS LONG, C AS LONG, d AS LONG, X AS LONG, S AS LONG, ac AS LONG) AS LONG
SELECT CASE strRound
CASE "FF"
'//////////
a = MD5LongAdd4(a, (b AND C) OR (NOT (b) AND d), X, ac)
a = MD5Rotate(a, S)
a = MD5LongAdd(a, b)
CASE "GG"
a = MD5LongAdd4(a, (b AND d) OR (C AND NOT (d)), X, ac)
a = MD5Rotate(a, S)
a = MD5LongAdd(a, b)
CASE "HH"
a = MD5LongAdd4(a, b XOR C XOR d, X, ac)
a = MD5Rotate(a, S)
a = MD5LongAdd(a, b)
CASE "II"
a = MD5LongAdd4(a, C XOR (b OR NOT (d)), X, ac)
a = MD5Rotate(a, S)
a = MD5LongAdd(a, b)
END SELECT
END FUNCTION
FUNCTION TRID() AS STRING
 
IM sngNum AS SINGLE, lngnum AS LONG
 
IM strResult AS STRING
sngNum = RND(2147483648#)
strResult = STR$(sngNum)
REPLACE "0." WITH "" IN strResult
REPLACE "." WITH "" IN strResult
REPLACE "E-" WITH "" IN strResult
'strResult = REPLACE(strResult, "0.", ""
'strResult = REPLACE(strResult, ".", ""
'strResult = REPLACE(strResult, "E-", ""
TRID = strResult
END FUNCTION
SUB MD5Decode(intLength AS INTEGER, lngOutBuffer() AS LONG, bytInBuffer() AS BYTE)
 
IM intDblIndex AS INTEGER
 
IM intByteIndex AS INTEGER
 
IM dblSum AS DOUBLE
intDblIndex = 0
FOR intByteIndex = 0 TO intLength - 1 STEP 4
dblSum = bytInBuffer(intByteIndex) + bytInBuffer(intByteIndex + 1) * 256# + bytInBuffer(intByteIndex + 2) * 65536# + bytInBuffer(intByteIndex + 3) * 16777216#
lngOutBuffer(intDblIndex) = MD5LongConversion(dblSum)
intDblIndex = (intDblIndex + 1)
NEXT intByteIndex
END SUB
SUB MD5Conversion(bytBuffer() AS BYTE)
 
IM X(16) AS LONG, a AS LONG
 
IM b AS LONG, C AS LONG
 
IM d AS LONG
a = arrLongConversion(1)
b = arrLongConversion(2)
C = arrLongConversion(3)
d = arrLongConversion(4)
MD5Decode 64, X(), bytBuffer()
'///////////////////////////////////////
MD5Round "FF", a, b, C, d, X(0), %S11, -680876936
MD5Round "FF", d, a, b, C, X(1), %S12, -389564586
MD5Round "FF", C, d, a, b, X(2), %S13, 606105819
MD5Round "FF", b, C, d, a, X(3), %S14, -1044525330
MD5Round "FF", a, b, C, d, X(4), %S11, -176418897
MD5Round "FF", d, a, b, C, X(5), %S12, 1200080426
MD5Round "FF", C, d, a, b, X(6), %S13, -1473231341
MD5Round "FF", b, C, d, a, X(7), %S14, -45705983
MD5Round "FF", a, b, C, d, X(8), %S11, 1770035416
MD5Round "FF", d, a, b, C, X(9), %S12, -1958414417
MD5Round "FF", C, d, a, b, X(10), %S13, -42063
MD5Round "FF", b, C, d, a, X(11), %S14, -1990404162
MD5Round "FF", a, b, C, d, X(12), %S11, 1804603682
MD5Round "FF", d, a, b, C, X(13), %S12, -40341101
MD5Round "FF", C, d, a, b, X(14), %S13, -1502002290
MD5Round "FF", b, C, d, a, X(15), %S14, 1236535329
MD5Round "GG", a, b, C, d, X(1), %S21, -165796510
MD5Round "GG", d, a, b, C, X(6), %S22, -1069501632
MD5Round "GG", C, d, a, b, X(11), %S23, 643717713
MD5Round "GG", b, C, d, a, X(0), %S24, -373897302
MD5Round "GG", a, b, C, d, X(5), %S21, -701558691
MD5Round "GG", d, a, b, C, X(10), %S22, 38016083
MD5Round "GG", C, d, a, b, X(15), %S23, -660478335
MD5Round "GG", b, C, d, a, X(4), %S24, -405537848
MD5Round "GG", a, b, C, d, X(9), %S21, 568446438
MD5Round "GG", d, a, b, C, X(14), %S22, -1019803690
MD5Round "GG", C, d, a, b, X(3), %S23, -187363961
MD5Round "GG", b, C, d, a, X(8), %S24, 1163531501
MD5Round "GG", a, b, C, d, X(13), %S21, -1444681467
MD5Round "GG", d, a, b, C, X(2), %S22, -51403784
MD5Round "GG", C, d, a, b, X(7), %S23, 1735328473
MD5Round "GG", b, C, d, a, X(12), %S24, -1926607734
MD5Round "HH", a, b, C, d, X(5), %S31, -378558
MD5Round "HH", d, a, b, C, X(8), %S32, -2022574463
MD5Round "HH", C, d, a, b, X(11), %S33, 1839030562
MD5Round "HH", b, C, d, a, X(14), %S34, -35309556
MD5Round "HH", a, b, C, d, X(1), %S31, -1530992060
MD5Round "HH", d, a, b, C, X(4), %S32, 1272893353
MD5Round "HH", C, d, a, b, X(7), %S33, -155497632
MD5Round "HH", b, C, d, a, X(10), %S34, -1094730640
MD5Round "HH", a, b, C, d, X(13), %S31, 681279174
MD5Round "HH", d, a, b, C, X(0), %S32, -358537222
MD5Round "HH", C, d, a, b, X(3), %S33, -722521979
MD5Round "HH", b, C, d, a, X(6), %S34, 76029189
MD5Round "HH", a, b, C, d, X(9), %S31, -640364487
MD5Round "HH", d, a, b, C, X(12), %S32, -421815835
MD5Round "HH", C, d, a, b, X(15), %S33, 530742520
MD5Round "HH", b, C, d, a, X(2), %S34, -995338651
MD5Round "II", a, b, C, d, X(0), %S41, -198630844
MD5Round "II", d, a, b, C, X(7), %S42, 1126891415
MD5Round "II", C, d, a, b, X(14), %S43, -1416354905
MD5Round "II", b, C, d, a, X(5), %S44, -57434055
MD5Round "II", a, b, C, d, X(12), %S41, 1700485571
MD5Round "II", d, a, b, C, X(3), %S42, -1894986606
MD5Round "II", C, d, a, b, X(10), %S43, -1051523
MD5Round "II", b, C, d, a, X(1), %S44, -2054922799
MD5Round "II", a, b, C, d, X(8), %S41, 1873313359
MD5Round "II", d, a, b, C, X(15), %S42, -30611744
MD5Round "II", C, d, a, b, X(6), %S43, -1560198380
MD5Round "II", b, C, d, a, X(13), %S44, 1309151649
MD5Round "II", a, b, C, d, X(4), %S41, -145523070
MD5Round "II", d, a, b, C, X(11), %S42, -1120210379
MD5Round "II", C, d, a, b, X(2), %S43, 718787259
MD5Round "II", b, C, d, a, X(9), %S44, -343485551
arrLongConversion(1) = MD5LongAdd(arrLongConversion(1), a)
arrLongConversion(2) = MD5LongAdd(arrLongConversion(2), b)
arrLongConversion(3) = MD5LongAdd(arrLongConversion(3), C)
arrLongConversion(4) = MD5LongAdd(arrLongConversion(4), d)
END SUB
FUNCTION MD564Split(lngLength AS LONG, bytBuffer() AS BYTE) AS STRING
 
IM lngBytesTotal AS LONG, lngBytesToAdd AS LONG
 
IM intLoop AS INTEGER, intLoop2 AS INTEGER, lngTrace AS LONG
 
IM intInnerLoop AS INTEGER, intLoop3 AS INTEGER
lngBytesTotal = lngTrack MOD 64
lngBytesToAdd = 64 - lngBytesTotal
lngTrack = (lngTrack + lngLength)
IF lngLength >= lngBytesToAdd THEN
FOR intLoop = 0 TO lngBytesToAdd - 1
arrSplit64(lngBytesTotal + intLoop) = bytBuffer(intLoop)
NEXT intLoop
MD5Conversion arrSplit64()
lngTrace = (lngLength) MOD 64
FOR intLoop2 = lngBytesToAdd TO lngLength - intLoop - lngTrace STEP 64
FOR intInnerLoop = 0 TO 63
arrSplit64(intInnerLoop) = bytBuffer(intLoop2 + intInnerLoop)
NEXT intInnerLoop
MD5Conversion arrSplit64()
'/////////////////
NEXT intLoop2
lngBytesTotal = 0
ELSE
intLoop2 = 0
END IF
FOR intLoop3 = 0 TO lngLength - intLoop2 - 1
arrSplit64(lngBytesTotal + intLoop3) = bytBuffer(intLoop2 + intLoop3)
NEXT intLoop3
END FUNCTION
FUNCTION MD5StringArray(strInput AS STRING) AS BYTE()
'///////////////////
 
IM intLoop AS INTEGER
 
IM bytBuffer() AS BYTE
REDIM bytBuffer(LEN(strInput))
FOR intLoop = 0 TO LEN(strInput) - 1
bytBuffer(intLoop) = ASC(MID$(strInput, intLoop + 1, 1))
NEXT intLoop
MD5StringArray() = bytBuffer()
'///////////////////
END FUNCTION
SUB MD5Finish()
 
IM dblBits AS DOUBLE
 
IM arrPadding(72) AS BYTE
 
IM lngBytesBuffered AS LONG
arrPadding(0) = &H80
dblBits = lngTrack * 8
lngBytesBuffered = lngTrack MOD 64
IF lngBytesBuffered <= 56 THEN
MD564Split (56 - lngBytesBuffered), arrPadding()
ELSE
MD564Split (120 - lngTrack), arrPadding()
END IF
arrPadding(0) = MD5LongConversion(dblBits) AND &HFF&
arrPadding(1) = MD5LongConversion(dblBits) \ 256 AND &HFF&
arrPadding(2) = MD5LongConversion(dblBits) \ 65536 AND &HFF&
arrPadding(3) = MD5LongConversion(dblBits) \ 16777216 AND &HFF&
arrPadding(4) = 0
arrPadding(5) = 0
arrPadding(6) = 0
arrPadding(7) = 0
MD564Split 8, arrPadding()
END SUB
FUNCTION MD5StringChange(lngnum AS LONG) AS STRING
 
IM bytA AS BYTE
 
IM bytB AS BYTE
 
IM bytC AS BYTE
 
IM bytD AS BYTE
 
IM ReturnBuf AS STRING
bytA = lngnum AND &HFF&
IF bytA < 16 THEN
ReturnBuf = "0" & HEX$(bytA)
ELSE
ReturnBuf = HEX$(bytA)
END IF
bytB = (lngnum AND &HFF00&
\ 256
IF bytB < 16 THEN
ReturnBuf = ReturnBuf + "0" + HEX$(bytB)
ELSE
ReturnBuf = ReturnBuf + HEX$(bytB)
END IF
bytC = (lngnum AND &HFF0000) \ 65536
IF bytC < 16 THEN
ReturnBuf = ReturnBuf + "0" + HEX$(bytC)
ELSE
ReturnBuf = ReturnBuf + HEX$(bytC)
END IF
IF lngnum < 0 THEN
bytD = ((lngnum AND &H7F000000) \ 16777216) OR &H80&
ELSE
bytD = (lngnum AND &HFF000000) \ 16777216
END IF
IF bytD < 16 THEN
ReturnBuf = ReturnBuf + "0" + HEX$(bytD)
ELSE
ReturnBuf = ReturnBuf + HEX$(bytD)
END IF
MD5StringChange = ReturnBuf
END FUNCTION
FUNCTION MD5Value() AS STRING
MD5Value = LCASE$(MD5StringChange(arrLongConversion(1)) + MD5StringChange(arrLongConversion(2)) + MD5StringChange(arrLongConversion(3)) + MD5StringChange(arrLongConversion(4)))
END FUNCTION
SUB MD5Start()
lngTrack = 0
arrLongConversion(1) = MD5LongConversion(1732584193)
arrLongConversion(2) = MD5LongConversion(4023233417)
arrLongConversion(3) = MD5LongConversion(2562383102)
arrLongConversion(4) = MD5LongConversion(271733878)
END SUB
FUNCTION CalculateMD5(strMessage AS STRING) AS STRING
 
IM bytBuffer() AS BYTE
 
IM arrLongConversion(4) AS GLOBAL LONG
'/////////////////////////////////////
 
IM arrSplit64(63) AS GLOBAL BYTE
 
IM intLoop AS INTEGER
'//////////////////
REDIM bytBuffer(LEN(strMessage))
FOR intLoop = 0 TO LEN(strMessage) - 1
bytBuffer(intLoop) = ASC(MID$(strMessage, intLoop + 1, 1))
NEXT intLoop
'MD5StringArray() = bytBuffer()
'bytBuffer() = MD5StringArray(strMessage)
'/////////////////
MD5Start
MD564Split LEN(strMessage), bytBuffer()
MD5Finish
CalculateMD5 = MD5Value
END FUNCTION