I've been trying to match a string to a pattern for password validation. e.g. password must contain upper/lower and special character.
I've used the StrCSpn (modified for case sensitivity) function to scan strings for a character, but I had to have a separate list for special characters and upper/lowercase letters. So the code is a bit bulky https://nsis.sourceforge.io/StrCSpn,_StrCSpnReverse:_Scan_strings_for_characters
Is there a way to use a regular expression in NSIS like here RegEx for at least 1 number, 1 lower case and 1 upper case letter
You could use the NSISpcre plug-in:
Function PasswordMatchesPolicy
Push $0
Push $1
Push $2
Push 0
Push 0
Exch 5
Push `^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*)$$` #stackoverflow.com/questions/43127814/regex-for-at-least-1-number-1-lower-case-and-1-upper-case-letter
NSISpcre::REMatches
Pop $0
${If} $0 == true
Pop $0
${For} $1 1 $0
Pop $2
${Next}
Push 1
${Else}
Push ""
${EndIf}
Exch 3
Pop $2
Pop $1
Pop $0
FunctionEnd
!include LogicLib.nsh
ShowInstDetails show
Section
!macro Test str
Push "${str}"
Call PasswordMatchesPolicy
Pop $0
${If} $0 <> 0
StrCpy $0 PASS
${Else}
StrCpy $0 FAIL
${EndIf}
DetailPrint "$0:${str}"
!macroend
!insertmacro Test "foo"
!insertmacro Test "Foo"
!insertmacro Test "Foo1"
!insertmacro Test "Foo#"
!insertmacro Test "Foo1#"
SectionEnd
Or if you only care about ASCII:
Function PasswordMatchesPolicy
!define /IfNDef C1_UPPER 0x0001
!define /IfNDef C1_LOWER 0x0002
!define /IfNDef C1_DIGIT 0x0004
!define /IfNDef C1_DEFINED 0x0200
System::Store S
System::Call 'KERNEL32::lstrcpyA(@r1,ms)'
StrCpy $5 ""
StrCpy $3 0
loop:
System::Call '*$1(&i$3,&i1.r4)'
${If} $4 <> 0
${If} $4 >= 65
${AndIf} $4 <= 90
IntOp $5 $5 | ${C1_UPPER}
${ElseIf} $4 >= 97
${AndIf} $4 <= 122
IntOp $5 $5 | ${C1_LOWER}
${ElseIf} $4 >= 48
${AndIf} $4 <= 57
IntOp $5 $5 | ${C1_DIGIT}
${Else}
IntOp $5 $5 | ${C1_DEFINED} ; Just mark it as "something"
${EndIf}
IntOp $3 $3 + 1
Goto loop
${EndIf}
IntOp $4 $5 & 3
${If} $4 = 3 ; C1_UPPER and C1_LOWER
${AndIf} $5 >= 4 ; Digit or symbol
Push 1
${Else}
Push 0
${EndIf}
System::Store L
FunctionEnd