8a823f06122b
broaden policy scraper: deeper DOM walk, label/div selectors, range/exact/min-only pattern forms, between/exactly text phrases
- time
- 2026-05-05 16:11 UTC · 5 months ago
- machine
- koh2
- parent
- d08bf4e3dd8a
↓ peach-browser-8a823f06.tar.gzatlas at this save
files changed3 files
manifest.firefox.json+1 −1manifest.json+1 −1src/content/policy.ts+23 −8manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.30.2",4+ "version": "2.32.0",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.31.0",4+ "version": "2.32.0",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",src/content/policy.ts+23 −8
@@ -27,11 +27,11 @@2727 if (desc) return desc.textContent ?? "";2828 }2929 let node: Element | null = el;30- for (let i = 0; i < 3; i++) {30+ for (let i = 0; i < 5; i++) {3131 node = node?.parentElement ?? null;3232 if (!node) break;3333 const hints = node.querySelectorAll(34- "p, span, li, small, .hint, .requirement, .password-rule"34+ "p, span, li, small, label, div, .hint, .requirement, .password-rule, .password-hint, .password-rules, .field-hint, .helper-text, .input-hint"3535 );3636 if (hints.length > 0) {3737 return Array.from(hints).map((h) => h.textContent).join(" ");@@ -50,18 +50,33 @@5050 if (maxLen > 0) policy.maxLength = maxLen;5151 if (passwordField?.pattern) {5252 const pat = passwordField.pattern;53- const minMatch = pat.match(/\{(\d+),/);54- const maxMatch = pat.match(/,(\d+)\}/);55- if (minMatch) policy.minLength = parseInt(minMatch[1]!);56- if (maxMatch) policy.maxLength = parseInt(maxMatch[1]!);53+ // .{N,M} — range; .{N,} — min only; .{N} — exact54+ const rangeMatch = pat.match(/\{(\d+),(\d+)\}/);55+ const minOnlyMatch = pat.match(/\{(\d+),\}/);56+ const exactMatch = pat.match(/\{(\d+)\}/);57+ if (rangeMatch) {58+ policy.minLength = parseInt(rangeMatch[1]!);59+ policy.maxLength = parseInt(rangeMatch[2]!);60+ } else if (minOnlyMatch) {61+ policy.minLength = parseInt(minOnlyMatch[1]!);62+ } else if (exactMatch) {63+ policy.minLength = parseInt(exactMatch[1]!);64+ policy.maxLength = parseInt(exactMatch[1]!);65+ }5766 }5867 5968 const text = extractNearbyText(passwordField);6069 61- const minMatch = text.match(/(?:at least|minimum|min)[^\d]*(\d+)/i);62- const maxMatch = text.match(/(?:at most|maximum|max|up to|cannot exceed|must not exceed|no more than)[^\d]*(\d+)/i);70+ const minMatch = text.match(/(?:at least|minimum|min(?:imum)?|must be (?:at least )?)(?:\D*?)(\d+)/i);71+ const maxMatch = text.match(/(?:at most|maximum|max(?:imum)?|up to|cannot exceed|must not exceed|no more than|must be (?:no more than |at most )?)(?:\D*?)(\d+)/i);72+ const betweenMatch = text.match(/between\D*?(\d+)\D+?(\d+)/i);73+ const exactMatch2 = text.match(/(?:exactly|must be)\D*?(\d+)\s*characters?/i);74+ if (betweenMatch && !policy.minLength) policy.minLength = parseInt(betweenMatch[1]!);75+ if (betweenMatch && !policy.maxLength) policy.maxLength = parseInt(betweenMatch[2]!);6376 if (minMatch && !policy.minLength) policy.minLength = parseInt(minMatch[1]!);6477 if (maxMatch && !policy.maxLength) policy.maxLength = parseInt(maxMatch[1]!);78+ if (exactMatch2 && !policy.minLength) policy.minLength = parseInt(exactMatch2[1]!);79+ if (exactMatch2 && !policy.maxLength) policy.maxLength = parseInt(exactMatch2[1]!);6580 6681 if (/no\s+(?:special|symbol)/i.test(text)) policy.forbidsSymbols = true;6782 if (/(?:special|symbol|punctuation)/i.test(text)) policy.requiresSymbols = true;