in tools/PasswordRulesParser.js [143:263]
function _canonicalizedPropertyValues(propertyValues, keepCustomCharacterClassFormatCompliant)
{
let asciiPrintableBitSet = new Array("~".codePointAt(0) - " ".codePointAt(0) + 1);
for (let propertyValue of propertyValues) {
if (propertyValue instanceof NamedCharacterClass) {
if (propertyValue.name === Identifier.UNICODE) {
return [new NamedCharacterClass(Identifier.UNICODE)];
}
if (propertyValue.name === Identifier.ASCII_PRINTABLE) {
return [new NamedCharacterClass(Identifier.ASCII_PRINTABLE)];
}
_markBitsForNamedCharacterClass(asciiPrintableBitSet, propertyValue);
}
else if (propertyValue instanceof CustomCharacterClass) {
_markBitsForCustomCharacterClass(asciiPrintableBitSet, propertyValue);
}
}
let charactersSeen = [];
function checkRange(start, end) {
let temp = [];
for (let i = _bitSetIndexForCharacter(start); i <= _bitSetIndexForCharacter(end); ++i) {
if (asciiPrintableBitSet[i]) {
temp.push(_characterAtBitSetIndex(i));
}
}
let result = temp.length === (_bitSetIndexForCharacter(end) - _bitSetIndexForCharacter(start) + 1);
if (!result) {
charactersSeen = charactersSeen.concat(temp);
}
return result;
}
let hasAllUpper = checkRange("A", "Z");
let hasAllLower = checkRange("a", "z");
let hasAllDigits = checkRange("0", "9");
// Check for special characters, accounting for characters that are given special treatment (i.e. '-' and ']')
let hasAllSpecial = false;
let hasDash = false;
let hasRightSquareBracket = false;
let temp = [];
for (let i = _bitSetIndexForCharacter(" "); i <= _bitSetIndexForCharacter("/"); ++i) {
if (!asciiPrintableBitSet[i]) {
continue;
}
let character = _characterAtBitSetIndex(i);
if (keepCustomCharacterClassFormatCompliant && character === "-") {
hasDash = true;
}
else {
temp.push(character);
}
}
for (let i = _bitSetIndexForCharacter(":"); i <= _bitSetIndexForCharacter("@"); ++i) {
if (asciiPrintableBitSet[i]) {
temp.push(_characterAtBitSetIndex(i));
}
}
for (let i = _bitSetIndexForCharacter("["); i <= _bitSetIndexForCharacter("`"); ++i) {
if (!asciiPrintableBitSet[i]) {
continue;
}
let character = _characterAtBitSetIndex(i);
if (keepCustomCharacterClassFormatCompliant && character === "]") {
hasRightSquareBracket = true;
}
else {
temp.push(character);
}
}
for (let i = _bitSetIndexForCharacter("{"); i <= _bitSetIndexForCharacter("~"); ++i) {
if (asciiPrintableBitSet[i]) {
temp.push(_characterAtBitSetIndex(i));
}
}
if (hasDash) {
temp.unshift("-");
}
if (hasRightSquareBracket) {
temp.push("]");
}
let numberOfSpecialCharacters = (_bitSetIndexForCharacter("/") - _bitSetIndexForCharacter(" ") + 1)
+ (_bitSetIndexForCharacter("@") - _bitSetIndexForCharacter(":") + 1)
+ (_bitSetIndexForCharacter("`") - _bitSetIndexForCharacter("[") + 1)
+ (_bitSetIndexForCharacter("~") - _bitSetIndexForCharacter("{") + 1);
hasAllSpecial = temp.length === numberOfSpecialCharacters;
if (!hasAllSpecial) {
charactersSeen = charactersSeen.concat(temp);
}
let result = [];
if (hasAllUpper && hasAllLower && hasAllDigits && hasAllSpecial) {
return [new NamedCharacterClass(Identifier.ASCII_PRINTABLE)];
}
if (hasAllUpper) {
result.push(new NamedCharacterClass(Identifier.UPPER));
}
if (hasAllLower) {
result.push(new NamedCharacterClass(Identifier.LOWER));
}
if (hasAllDigits) {
result.push(new NamedCharacterClass(Identifier.DIGIT));
}
if (hasAllSpecial) {
result.push(new NamedCharacterClass(Identifier.SPECIAL));
}
if (charactersSeen.length) {
result.push(new CustomCharacterClass(charactersSeen));
}
return result;
}