Files
SnowLuma/.pnpm-store/v11/files/5e/dd2f21b9a43b76c664b3d915a0503ac97a29a8686848c7fa4d9dcf524267b4ed08b36291a06f58972104759a424fcb2e9b08f63038a87d8f3adab6e5989844
TanTan 2a69b23b47
Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Skipped
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

120 lines
3.0 KiB
Plaintext

'use strict';
var _const = require('../../data/const.cjs');
var types = require('../../types.cjs');
/*
*-------------------------------------------------------------------------------
* sequences (abcdef) ------------------------------
*-------------------------------------------------------------------------------
*/
class MatchSequence extends types.MatcherBaseClass {
constructor() {
super(...arguments);
this.MAX_DELTA = 5;
}
// eslint-disable-next-line max-statements
match({
password
}) {
/*
* Identifies sequences by looking for repeated differences in unicode codepoint.
* this allows skipping, such as 9753, and also matches some extended unicode sequences
* such as Greek and Cyrillic alphabets.
*
* for example, consider the input 'abcdb975zy'
*
* password: a b c d b 9 7 5 z y
* index: 0 1 2 3 4 5 6 7 8 9
* delta: 1 1 1 -2 -41 -2 -2 69 1
*
* expected result:
* [(i, j, delta), ...] = [(0, 3, 1), (5, 7, -2), (8, 9, 1)]
*/
const result = [];
if (password.length === 1) {
return [];
}
let i = 0;
let lastDelta = null;
const passwordLength = password.length;
for (let k = 1; k < passwordLength; k += 1) {
const delta = password.charCodeAt(k) - password.charCodeAt(k - 1);
if (lastDelta === null) {
lastDelta = delta;
}
if (delta !== lastDelta) {
const j = k - 1;
this.update({
i,
j,
delta: lastDelta,
password,
result
});
i = j;
lastDelta = delta;
}
}
this.update({
i,
j: passwordLength - 1,
delta: lastDelta,
password,
result
});
return result;
}
update({
i,
j,
delta,
password,
result
}) {
if (j - i > 1 || Math.abs(delta) === 1) {
const absoluteDelta = Math.abs(delta);
if (absoluteDelta > 0 && absoluteDelta <= this.MAX_DELTA) {
const token = password.slice(i, j + 1 || 9e9);
const {
sequenceName,
sequenceSpace
} = this.getSequence(token);
return result.push({
pattern: 'sequence',
i,
j,
token: password.slice(i, j + 1 || 9e9),
sequenceName,
sequenceSpace,
ascending: delta > 0
});
}
}
return null;
}
getSequence(token) {
// TODO conservatively stick with roman alphabet size.
// (this could be improved)
let sequenceName = 'unicode';
let sequenceSpace = 26;
if (_const.ALL_LOWER.test(token)) {
sequenceName = 'lower';
sequenceSpace = 26;
} else if (_const.ALL_UPPER.test(token)) {
sequenceName = 'upper';
sequenceSpace = 26;
} else if (_const.ALL_DIGIT.test(token)) {
sequenceName = 'digits';
sequenceSpace = 10;
}
return {
sequenceName,
sequenceSpace
};
}
}
module.exports = MatchSequence;
//# sourceMappingURL=matching.cjs.map