mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-19 15:18:02 -04:00
Update form detection and popup icon display (#622)
This commit is contained in:
@@ -228,8 +228,10 @@ export function createAutofillPopup(input: HTMLInputElement, credentials: Creden
|
||||
createButton.style.backgroundColor = isDarkMode() ? '#374151' : '#f3f4f6';
|
||||
});
|
||||
|
||||
// Handle create button click
|
||||
const handleCreateClick = async (e: Event) => {
|
||||
/**
|
||||
* Handle create button click
|
||||
*/
|
||||
const handleCreateClick = async (e: Event) : Promise<void> => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
@@ -682,8 +684,11 @@ function createCredentialList(credentials: Credential[], input: HTMLInputElement
|
||||
// Handle base64 image data
|
||||
if (cred.Logo) {
|
||||
try {
|
||||
const base64Logo = base64Encode(cred.Logo as Uint8Array<ArrayBufferLike>);
|
||||
imgElement.src = `data:image/x-icon;base64,${base64Logo}`;
|
||||
const logoBytes = toUint8Array(cred.Logo);
|
||||
const base64Logo = base64Encode(logoBytes);
|
||||
// Detect image type from first few bytes
|
||||
const mimeType = detectMimeType(logoBytes);
|
||||
imgElement.src = `data:${mimeType};base64,${base64Logo}`;
|
||||
} catch (error) {
|
||||
console.error('Error setting logo:', error);
|
||||
imgElement.src = `data:image/x-icon;base64,${placeholderBase64}`;
|
||||
@@ -1070,23 +1075,33 @@ export function openAutofillPopup(input: HTMLInputElement) : void {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert various binary data formats to Uint8Array
|
||||
*/
|
||||
function toUint8Array(buffer: Uint8Array | number[] | {[key: number]: number}): Uint8Array {
|
||||
if (buffer instanceof Uint8Array) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if (Array.isArray(buffer)) {
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
// Handle object with numeric keys
|
||||
const length = Object.keys(buffer).length;
|
||||
const arr = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
arr[i] = buffer[i];
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64 encode binary data.
|
||||
*/
|
||||
function base64Encode(buffer: Uint8Array | number[] | {[key: number]: number}): string | null {
|
||||
try {
|
||||
// Handle object with numeric keys
|
||||
if (typeof buffer === 'object' && !Array.isArray(buffer) && !(buffer instanceof Uint8Array)) {
|
||||
const length = Object.keys(buffer).length;
|
||||
const arr = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
arr[i] = buffer[i];
|
||||
}
|
||||
buffer = arr;
|
||||
}
|
||||
|
||||
// Convert to array if Uint8Array
|
||||
const arr = Array.from(buffer as Uint8Array | number[]);
|
||||
const arr = Array.from(toUint8Array(buffer));
|
||||
return btoa(arr.reduce((data, byte) => data + String.fromCharCode(byte), ''));
|
||||
} catch (error) {
|
||||
console.error('Error encoding to base64:', error);
|
||||
@@ -1143,3 +1158,43 @@ async function getFaviconBytes(document: Document): Promise<Uint8Array | null> {
|
||||
|
||||
return null; // Return null if no favicon could be downloaded
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect MIME type from file signature (magic numbers)
|
||||
*/
|
||||
function detectMimeType(bytes: Uint8Array): string {
|
||||
/**
|
||||
* Check if the file is an SVG file.
|
||||
*/
|
||||
const isSvg = () : boolean => {
|
||||
const header = new TextDecoder().decode(bytes.slice(0, 5)).toLowerCase();
|
||||
return header.includes('<?xml') || header.includes('<svg');
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the file is an ICO file.
|
||||
*/
|
||||
const isIco = () : boolean => {
|
||||
return bytes[0] === 0x00 && bytes[1] === 0x00 && bytes[2] === 0x01 && bytes[3] === 0x00;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the file is an PNG file.
|
||||
*/
|
||||
const isPng = () : boolean => {
|
||||
return bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4E && bytes[3] === 0x47;
|
||||
};
|
||||
|
||||
if (isSvg()) {
|
||||
return 'image/svg+xml';
|
||||
}
|
||||
if (isIco()) {
|
||||
return 'image/x-icon';
|
||||
}
|
||||
if (isPng()) {
|
||||
return 'image/png';
|
||||
}
|
||||
|
||||
// Default to x-icon if unknown
|
||||
return 'image/x-icon';
|
||||
}
|
||||
|
||||
@@ -101,15 +101,33 @@ export class FormDetector {
|
||||
}
|
||||
}
|
||||
|
||||
// Check for parent label
|
||||
// Check for parent label and table cell structure
|
||||
let currentElement = input;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
// Check for parent label
|
||||
const parentLabel = currentElement.closest('label');
|
||||
if (parentLabel) {
|
||||
attributes.push(parentLabel.textContent?.toLowerCase() ?? '');
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for table cell structure
|
||||
const parentTd = currentElement.closest('td');
|
||||
if (parentTd) {
|
||||
// Get the parent row
|
||||
const parentTr = parentTd.closest('tr');
|
||||
if (parentTr) {
|
||||
// Check all sibling cells in the row
|
||||
const siblingTds = parentTr.querySelectorAll('td');
|
||||
for (const td of siblingTds) {
|
||||
if (td !== parentTd) { // Skip the cell containing the input
|
||||
attributes.push(td.textContent?.toLowerCase() ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
break; // Found table structure, no need to continue up the tree
|
||||
}
|
||||
|
||||
if (currentElement.parentElement) {
|
||||
currentElement = currentElement.parentElement as HTMLInputElement;
|
||||
} else {
|
||||
|
||||
@@ -44,6 +44,13 @@ describe('FormDetector English tests', () => {
|
||||
testField(FormField.LastName, 'fbclc_lName', htmlFile);
|
||||
});
|
||||
|
||||
describe('English registration form 5 detection', () => {
|
||||
const htmlFile = 'en-registration-form5.html';
|
||||
|
||||
testField(FormField.Username, 'aliasvault-input-7owmnahd9', htmlFile);
|
||||
testField(FormField.Password, 'aliasvault-input-ienw3qgxv', htmlFile);
|
||||
});
|
||||
|
||||
describe('English email form 1 detection', () => {
|
||||
const htmlFile = 'en-email-form1.html';
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<html lang="en"><head><meta name="referrer" content="origin"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="icon" href="y18.svg"><style>com-strongbox-extension {visibility: visible !important; /* Ensure visibility for Strongbox Extension */}</style><style>com-strongbox-extension {visibility: visible !important; /* Ensure visibility for Strongbox Extension */}</style><style>com-strongbox-extension {visibility: visible !important; /* Ensure visibility for Strongbox Extension */}</style></head><body><b>Login</b><br><br>
|
||||
<form action="login" method="post"><input type="hidden" name="goto" value="news"><table border="0"><tbody><tr><td>username:</td><td><input type="text" name="acct" size="20" autocorrect="off" spellcheck="false" autocapitalize="off" autofocus="true" id="aliasvault-input-xahcz4tlf" autocomplete="false"></td></tr><tr><td>password:</td><td><input type="password" name="pw" size="20"></td></tr></tbody></table><br>
|
||||
<input type="submit" value="login"></form><a href="forgot">Forgot your password?</a><br><br>
|
||||
<b>Create Account</b><br><br>
|
||||
<form action="login" method="post"><input type="hidden" name="goto" value="news"><input type="hidden" name="creating" value="t"><table border="0"><tbody><tr><td>username:</td><td><input type="text" name="acct" size="20" autocorrect="off" spellcheck="false" autocapitalize="off" id="aliasvault-input-7owmnahd9" autocomplete="false"></td></tr><tr><td>password:</td><td><input type="password" name="pw" size="20" id="aliasvault-input-ienw3qgxv" autocomplete="false"></td></tr></tbody></table><br>
|
||||
<input type="submit" value="create account"></form></body></html>
|
||||
@@ -57,3 +57,4 @@ The following websites have been known to cause issues in the past (but should b
|
||||
| https://www.paprika-shopping.nl/nieuwsbrief/newsletter-register-landing.html | Popup CSS style conflicts |
|
||||
| https://bloshing.com/inschrijven-nieuwsbrief | Popup CSS style conflicts |
|
||||
| https://gamefaqs.gamespot.com/user | Popup buttons not working |
|
||||
| https://news.ycombinator.com/login?goto=news | Popup logo not showing due to SVG format after identity creation |
|
||||
Reference in New Issue
Block a user