allow single files in base64 scanner

This commit is contained in:
2026-05-08 15:09:54 +08:00
parent e42002f5de
commit aa9b9846ca
3 changed files with 64 additions and 10 deletions

View File

@@ -29,19 +29,39 @@ export function openBase64Scanner(_context: vscode.ExtensionContext) {
if (picked && picked[0]) {
panel.webview.postMessage({ type: 'folderPicked', path: picked[0].fsPath });
}
} else if (msg.type === 'pickFiles') {
const picked = await vscode.window.showOpenDialog({
canSelectFolders: false,
canSelectFiles: true,
canSelectMany: true,
openLabel: 'Select Files',
filters: { 'HTML': ['html', 'htm'] },
});
if (picked && picked.length) {
panel.webview.postMessage({ type: 'filesPicked', paths: picked.map(u => u.fsPath) });
}
} else if (msg.type === 'scan') {
const folder: string = msg.folder;
if (!folder || !fs.existsSync(folder)) {
panel.webview.postMessage({ type: 'results', results: [], error: 'Invalid folder' });
const folder: string | undefined = msg.folder;
const files: string[] | undefined = msg.files;
let targets: string[] = [];
let baseDir = '';
if (files && files.length) {
targets = files.filter(f => fs.existsSync(f));
baseDir = targets.length ? commonBaseDir(targets) : '';
} else if (folder && fs.existsSync(folder)) {
targets = await collectHtmlFiles(folder);
baseDir = folder;
} else {
panel.webview.postMessage({ type: 'results', results: [], error: 'Pick a folder or files first' });
return;
}
const htmlFiles = await collectHtmlFiles(folder);
const results: { file: string; ok: boolean; assets: string[] }[] = [];
for (const file of htmlFiles) {
for (const file of targets) {
try {
const content = fs.readFileSync(file, 'utf8');
const offenders = findNonBase64Assets(content);
results.push({ file: path.relative(folder, file), ok: offenders.length === 0, assets: offenders });
const display = baseDir ? path.relative(baseDir, file) || path.basename(file) : file;
results.push({ file: display, ok: offenders.length === 0, assets: offenders });
} catch {
// skip unreadable
}
@@ -51,6 +71,16 @@ export function openBase64Scanner(_context: vscode.ExtensionContext) {
});
}
function commonBaseDir(files: string[]): string {
if (files.length === 0) return '';
if (files.length === 1) return path.dirname(files[0]);
const split = files.map(f => path.dirname(f).split(path.sep));
const first = split[0];
let i = 0;
while (i < first.length && split.every(parts => parts[i] === first[i])) i++;
return first.slice(0, i).join(path.sep);
}
async function collectHtmlFiles(root: string): Promise<string[]> {
const out: string[] = [];
const stack: string[] = [root];
@@ -132,9 +162,11 @@ function getHtml(): string {
<h2>Base64 Asset Scanner</h2>
<div class="row">
<input id="folder" type="text" placeholder="Folder to scan recursively..." />
<button id="pick">Browse...</button>
<button id="pick">Browse Folder...</button>
<button id="pickFiles">Pick Files...</button>
<button id="scan">Scan</button>
</div>
<div id="selection" class="summary"></div>
<div id="status"></div>
<div id="results"></div>
<script>
@@ -143,22 +175,43 @@ function getHtml(): string {
const folderEl = document.getElementById('folder');
const statusEl = document.getElementById('status');
const resultsEl = document.getElementById('results');
const selectionEl = document.getElementById('selection');
let pickedFiles = [];
function clearFiles() {
pickedFiles = [];
selectionEl.textContent = '';
}
folderEl.addEventListener('input', clearFiles);
document.getElementById('pick').addEventListener('click', () => {
vscode.postMessage({ type: 'pickFolder' });
});
document.getElementById('pickFiles').addEventListener('click', () => {
vscode.postMessage({ type: 'pickFiles' });
});
document.getElementById('scan').addEventListener('click', () => {
const folder = folderEl.value.trim();
if (!folder) { statusEl.textContent = 'Pick a folder first.'; return; }
statusEl.textContent = 'Scanning...';
resultsEl.innerHTML = '';
vscode.postMessage({ type: 'scan', folder });
if (pickedFiles.length) {
vscode.postMessage({ type: 'scan', files: pickedFiles });
} else {
const folder = folderEl.value.trim();
if (!folder) { statusEl.textContent = 'Pick a folder or files first.'; return; }
vscode.postMessage({ type: 'scan', folder });
}
});
window.addEventListener('message', (event) => {
const msg = event.data;
if (msg.type === 'folderPicked') {
folderEl.value = msg.path;
clearFiles();
} else if (msg.type === 'filesPicked') {
pickedFiles = msg.paths;
folderEl.value = '';
selectionEl.textContent = pickedFiles.length + ' file(s) selected';
} else if (msg.type === 'results') {
if (msg.error) { statusEl.textContent = 'Error: ' + msg.error; return; }
const total = msg.results.length;