4

I want to validate the password to include at least 1 Arabic or English letter and at least 1 Arabic or English number and at leats 8 length password, my old code that was made for English only was like :

let passwordRegex = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"
if (!NSPredicate(format:"SELF MATCHES %@",passwordRegex).evaluate(with: password)){
    return false
}

and then i found this answer for Arabic characters and digits, then i tried to merge both like this :

let passwordRegex = "^(?=.*[A-Za-zء-ي])(?=.*٠-٩\\d)[A-Za-zء-ي٠-٩\\d]{8,}$"
if (!NSPredicate(format:"SELF MATCHES %@",passwordRegex).evaluate(with: password)){
    return false
}

please advise what's wrong, thanks in advance

Mostafa Sultan
  • 2,268
  • 2
  • 20
  • 36

1 Answers1

4

Since an English or Arabic letter regex (as described in this answer you linked to, also, see this answer, too) is [a-zA-Za-z\u0621-\u064A] and an English or Arabic digit regex is [0-9\u0660-\u0669] you may use

let passwordRegex = "^(?=.*[a-zA-Z\\u0621-\\u064A])(?=.*[0-9\\u0660-\\u0669])[a-zA-Za-z\\u0621-\\u064A0-9\\u0660-\\u0669]{8,}$"

NOTE: you do not need the outer ^ and $ anchors because MATCHES requires the pattern to match the whole string input.

Another way to match an Arabic letter with ICU regex used in Swift is to use [\p{L}&&[\p{script=Arabic}]] (it is an intersection inside a character class, it matches any letter but from the Arabic character set). Same with a digit: [\p{N}&&[\p{script=Arabic}]]. Then, the regex will look like

let passwordRegex = "^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$"

So, here

  • [\\p{L}&&[\\p{script=Arabic}A-Za-z]] - any letter but it should belong to either ASCII letters or Arabic script
  • [\\p{N}&&[\\p{script=Arabic}0-9]] - any digit but either from 0-9 range or Arabic script
  • [\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]] - any letter or digit but only from the ASCII 0-9, A-Z, a-z and Arabic script.

Note also, that in order to match any letters, you may use\p{L} and to match any digits you may use \d (they are Unicode aware in ICU library). So, *in case t does not matter if the letters or digits are Arabic, English, Greek or whatever, you may use

let passwordRegex = "^(?=.*\\p{L})(?=.*\\d)[\\p{L}\\d]{8,}$"
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Dear Stribizew, can you give me a hint how to just add one more detail, i want that validation to accept also 0 or more special characters, i found an example but it force at least one special character, but i want to just make it available for the user to user, so i made the code like this but it didn't work : let passwordRegex = "^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$" – Mostafa Sultan Apr 28 '18 at 14:28
  • @Alshcompiler If you just want to let users enter any chars, replace `[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}` with `.{8,}`. – Wiktor Stribiżew Apr 28 '18 at 14:52
  • but user will have to enter at least 1 Arabic/English letter and number right ? – Mostafa Sultan Apr 28 '18 at 15:09
  • but why when i add the special characters to that validator like this it doesn't recognize those special characters like this : `[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9!@#$%^&*()-_=+{}|?>.<,:;~`’]]{8,} ` – Mostafa Sultan Apr 28 '18 at 15:12
  • in case i don't want some other characters :"D – Mostafa Sultan Apr 28 '18 at 15:13
  • 1
    @Alshcompiler It does not work because you placed them into the intersected class,but the other class does not match punctuation. You may use it like `(?:[\\p{L}&&[\\p{script=Arabic}]]|[a-zA-Z0-9!@#$%^&*()\\-_=+{}|?>.<,:;~’]){8,}` - make sure you escape the `-` or put it at the end of the character class. – Wiktor Stribiżew Apr 28 '18 at 16:47
  • Thanks again for your continuous support :) – Mostafa Sultan Apr 28 '18 at 17:55
  • @WiktorStribiżew i want to add special characters in this let passwordRegex = "^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$" . How to add ? – Chandan Jee Jul 17 '20 at 11:58
  • i try (?:[\\p{L}&&[\\p{script=Arabic}]]|[a-zA-Z0-9!@#$%^&*()\\-_=+{}|?>.<,:;~’]){8,} but its not working for me. – Chandan Jee Jul 17 '20 at 11:58
  • @ChandanJee ``"^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}\\p{P}\\p{S}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$"`` – Wiktor Stribiżew Jul 17 '20 at 12:04
  • @WiktorStribiżew it is not Working for me. func isArabicCheckTextSufficientComplexityUpperCaseNumber() -> Bool{ let passwordRegex = "^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}\\p{P}\\p{S}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$" let texttest = NSPredicate(format:"SELF MATCHES %@", passwordRegex) let result = texttest.evaluate(with: self) print("\(result)") return result } – Chandan Jee Jul 17 '20 at 12:10
  • @WiktorStribiżew can you please help me? – Chandan Jee Jul 17 '20 at 12:11