WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

RegExp

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Luhn Number Validation

 Keywords: Luhn Number Validation Validate Algorithm Modulus 10 Checksum Formula Dredit Card RegExp VBScript.RegExp

;==========================================================================================================================================
; Luhn number validation.
;
; The Luhn algorithm, also known as the "modulus 10" algorithm, is a simple checksum formula
; used to validate a variety of identification numbers, such as credit card numbers.
;
; This WinBatch example script scans all text files in a folder tree for so-called
; Luhn number strings, and creates a text file containing a list of validated Luhn numbers.
;
; This script handles Luhn numbers of different length and different formats.
; This script uses a simplified version of the Luhn algorithm, implemented by a lookup table.
;
; See also: http://en.wikipedia.org/wiki/Luhn_algorithm
; See example by Ozan Yigit, "http://nextbit.blogspot.com/2007/06/doing-luhn-checksum-simply.html".
;
; (c)Detlev Dalitz.20091209.
;==========================================================================================================================================

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfAskLine (strAL_Title, strAL_Prompt, strAL_Default, intAL_Format)
Return AskLine (strAL_Title, strAL_Prompt, strAL_Default, intAL_Format)
:CANCEL
Return "" ; Return empty string if dialog has been cancelled resp. closed by escape key.
;..........................................................................................................................................
; strAL_Title   = "" ; Title of the dialog box.
; strAL_Prompt  = "" ; Question to be put to the user.
; strAL_Default = "" ; Default answer.
; intAL_Format  = 0  ; Format as ANSI string.
; intAL_Format  = 1  ; Format as Unicode string.
; intAL_Format  = 2  ; Format as hex string, with four hex bytes per Unicode character.
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfCreateLuhnTable ()
arrLuhnTable = ArrDimension (10, 10)
For intI = 0 To 9
   For intN = 0 To 9
      intT = intI + intI
      If intT > 9 Then intT = intT - 9
      arrLuhnTable[intI, intN] = intT + intN
   Next
Next
Return arrLuhnTable
;..........................................................................................................................................
; This UDF udfCreateLuhnTable generates all two digit sequences, with appropriate Luhn translation of the first digit.
; This UDF is used in conjunction with the UDF udfIsValidLuhnNumber.
; The function returns a Dim-2 WinBatch array.
;
; See also: http://en.wikipedia.org/wiki/Luhn_algorithm
; See also: http://nextbit.blogspot.com/2007/06/doing-luhn-checksum-simply.html
; Detlev Dalitz.20091209.
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfIsValidLuhnNumber (arrLuhnTable, strLuhnNumber)
If StrReplace (strLuhnNumber, "0", "") == "" Then Return @FALSE
intLen = StrLen (strLuhnNumber)
If intLen < 2 Then Return @FALSE
arrN = ArrayFromStr (strLuhnNumber)
intSum = 0
intPos = 0
If intLen & 1 ; If the number length is odd, then save and skip the first digit.
   intSum = arrN[0]
   intPos = 1
EndIf
While intPos < intLen
   intSum = intSum + arrLuhnTable[arrN[intPos], arrN[intPos + 1]]
   intPos = intPos + 2
EndWhile
Return !(intSum mod 10)
;..........................................................................................................................................
; This UDF udfIsValidLuhnNumber validates a so-called Luhn number string (just digits).
; This UDF requires an instance of the Luhn lookup table array, which is a Dim-2 WinBatch array, created by the UDF udfCreateLuhnTable.
; The function returns the boolean value @TRUE resp. @FALSE depending on the validation.
;
; See also: http://en.wikipedia.org/wiki/Luhn_algorithm
; See also: http://nextbit.blogspot.com/2007/06/doing-luhn-checksum-simply.html
; Detlev Dalitz.20091209.
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

; Main.

strAL_Title = "Create list of Credit Card numbers" ; Title of the dialog box.
strAL_Prompt = "Input starting directory" ; Question to be put to the user.
strAL_Default = "W:\" ; Default answer.
intAL_Format = 0 ; Format as ANSI string.
strStartDirectory = udfAskLine (strAL_Title, strAL_Prompt, strAL_Default, intAL_Format)
If strStartDirectory == "" Then Goto CANCEL
DropWild ("strAL_*")
DropWild ("intAL_*")

strMsgFound = @LF : @LF : "Found: "
strMsgTitle = "Searching for Credit Card numbers"
strMsgText = ""

BoxOpen (strMsgTitle, strMsgText)
WinPlace (200, 100, 800, 500, "")

; Filename for valid Credit Card numbers.
strTime = StrReplace (TimeYmdHms (), ":", "")
strTime = StrSub (strTime, 1, 8) : "." : StrSub (strTime, 9, 6)
strCCValidFile = DirScript () : strTime : ".CC.valid.txt"
Drop (strTime)
; Open output file.
hdlFW = FileOpen (strCCValidFile, "WRITE")

; Define RegExp COM object 1.
; See also: http://www.regular-expressions.info/creditcard.html
objRegExp1 = ObjectCreate ("VBScript.RegExp")
objRegExp1.Global = @TRUE
objRegExp1.IgnoreCase = @FALSE
objRegExp1.MultiLine = @FALSE
;objRegExp1.Pattern = "(\d{4}-\d{4}-\d{4}-\d{4}|\d{16}|\d{4} \d{4} \d{4} \d{4})"
;objRegExp1.Pattern = "(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})"
objRegExp1.Pattern = "(?:\d[ -]*?){13,16}"

; Define RegExp COM object 2.
; Same as: StrClean (strTest, "0123456789", "", @TRUE, 2)
objRegExp2 = ObjectCreate ("VBScript.RegExp")
objRegExp2.Global = @TRUE
objRegExp2.IgnoreCase = @FALSE
objRegExp2.MultiLine = @FALSE
objRegExp2.Pattern = "[^\d]+"

; Create Luhn lookup table.
arrLuhnTable = udfCreateLuhnTable ()

; Initialize "File and Folder" extender and flags for readability.
AddExtender ("wwfaf44i.dll")
;intFFNoFlags = 0     ; No Flags.
;intFFHidden = 1      ; Include hidden files.
;intFFSystem = 2      ; Include system files.
;intFFFolders = 4     ; Inspect  subfolder names also.
;intFFFindFolders = 8 ; Only inspect subfolder names not file names.
intFFRecurse = 16    ; Recurse through subfolders.
;intFFNoPathInfo = 32 ; Do not return path information to files or folders found.
;intFFNoRedirect = 64 ; Do not turn off file redirection for x64 windows.

; Open a "File and Folder" search handle.
hdlFF = fafOpen (strStartDirectory, "*.txt", intFFRecurse)

; Perform the search.
While @TRUE
   strFilename = fafFind (hdlFF)
   If strFilename == "" Then Break
   strMsgText = "Reading file ..." : @LF : StrReplace (strFilename, "\", "\" : @LF)
   BoxText (strMsgText)
   hdlFR = FileOpen (strFilename, "READ")
   intLine = 0
   While @TRUE
      strLine = FileRead (hdlFR)
      If strLine == "*EOF*" Then Break
      intLine = intLine + 1
      If !objRegExp1.Test(strLine) Then Continue
      objMatches = objRegExp1.Execute(strLine)
      ForEach objMatch In objMatches
         strLuhnNumber = objRegExp2.Replace(objMatch.Value, "")
         If udfIsValidLuhnNumber (arrLuhnTable, strLuhnNumber)
            FileWrite (hdlFW, StrLen (strLuhnNumber) : "|" : objMatch.Value : "|" : intLine : "|" : objMatch.FirstIndex : "|" : '"' : strFilename : '"')
            BoxText (strMsgText : strMsgFound : objMatch.Value)
         EndIf
      Next
   EndWhile
   hdlFR = FileClose (hdlFR)
EndWhile

; Close search handle.
intResult = fafClose (hdlFF)

; Close output file.
hdlFW = FileClose (hdlFW)

; Release COM objects.
objRegExp1 = 0
objRegExp2 = 0

; Display output file.
Run (strCCValidFile, "")

; Structure of output line per single match:
; Count digits|Luhn number|Line in file|Position in line|Filepath

; Example strings which are valid Luhn numbers.
; 16: 1123 4567 8901 2345
; 16: 1123-4567-8901-2345
; 16: 1123456789012345
; 16: 1-5-21-1614895754-2
; 15: 792101347871681
; 15: 048 049 050 051 052
; 14: 10881411 346431
; 14: 79769313486231
; 13: 3-0-1-2-0-6-0-1-4-6-4-1-4
; 13: 8 00 00 00 18 10 00

:CANCEL
Exit

Article ID:   W18165
Filename:   Luhn Number Validation.txt
File Created: 2009:12:09:11:09:24
Last Updated: 2009:12:09:11:09:24