Skip to content
This repository was archived by the owner on May 29, 2025. It is now read-only.

Commit 2048f07

Browse files
authored
Update index.html
Signed-off-by: Blake Arnold <[email protected]>
1 parent 4ea1d56 commit 2048f07

File tree

1 file changed

+95
-38
lines changed

1 file changed

+95
-38
lines changed

index.html

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@
156156
background: #005fa3;
157157
}
158158

159+
.file-list {
160+
margin: 8px 0 14px 0;
161+
padding: 0;
162+
list-style: none;
163+
font-size: 14px;
164+
}
165+
.file-list li {
166+
margin: 0 0 3px 0;
167+
padding: 2px 0 2px 16px;
168+
background: url('data:image/svg+xml;utf8,<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" r="5" fill="%2388c" /></svg>') 0 6px no-repeat;
169+
background-size: 10px 10px;
170+
color: #444;
171+
word-break: break-all;
172+
}
173+
159174
@media (max-width: 600px) {
160175
.tab-content {
161176
padding: 16px 4vw;
@@ -193,9 +208,10 @@
193208
Plaintext:
194209
<textarea id="plaintext"></textarea>
195210
<button type="button" onclick="encrypt()">Encrypt</button>
196-
<input type="file" id="fileInput" style="display:none" />
197-
<button type="button" onclick="document.getElementById('fileInput').click()">Attach File</button>
198-
<button type="button" id="downloadAttachedBtn" style="display:none" onclick="downloadAttachedFile()">Download Attached File</button>
211+
<input type="file" id="fileInput" style="display:none" multiple />
212+
<button type="button" onclick="document.getElementById('fileInput').click()">Attach File(s)</button>
213+
<ul class="file-list" id="attachedFilesList"></ul>
214+
<button type="button" id="downloadAttachedBtn" style="display:none" onclick="downloadAttachedFile()">Download Attached File(s)</button>
199215
</div>
200216
<div id="tab2" class="tab-content">
201217
Ciphertext:
@@ -237,22 +253,28 @@
237253
return sha256(multiplied.toString());
238254
}
239255

240-
let attachedFile = null;
241-
let attachedFilename = "";
242-
let lastDecryptedFile = null;
243-
let lastDecryptedFilename = "";
256+
let attachedFiles = [];
257+
let lastDecryptedFiles = [];
244258

245259
document.getElementById('fileInput').addEventListener('change', function(evt) {
246-
if (evt.target.files.length > 0) {
247-
attachedFile = evt.target.files[0];
248-
attachedFilename = attachedFile.name;
249-
document.getElementById('downloadAttachedBtn').style.display = "none";
250-
} else {
251-
attachedFile = null;
252-
attachedFilename = "";
253-
}
260+
const files = Array.from(evt.target.files);
261+
attachedFiles = files;
262+
updateAttachedFilesList();
263+
document.getElementById('downloadAttachedBtn').style.display = "none";
254264
});
255265

266+
function updateAttachedFilesList() {
267+
const list = document.getElementById('attachedFilesList');
268+
list.innerHTML = "";
269+
if (attachedFiles.length > 0) {
270+
attachedFiles.forEach(f => {
271+
const li = document.createElement('li');
272+
li.textContent = f.name;
273+
list.appendChild(li);
274+
});
275+
}
276+
}
277+
256278
function fileToBase64(file) {
257279
return new Promise((resolve, reject) => {
258280
const reader = new FileReader();
@@ -281,12 +303,18 @@
281303
document.getElementById('num').value = num;
282304
}
283305
let envelope = null;
284-
if (attachedFile) {
285-
const fileDataB64 = await fileToBase64(attachedFile);
306+
if (attachedFiles.length > 0) {
307+
const filesArr = [];
308+
for (const file of attachedFiles) {
309+
const fileDataB64 = await fileToBase64(file);
310+
filesArr.push({
311+
n: file.name,
312+
d: fileDataB64
313+
});
314+
}
286315
envelope = JSON.stringify({
287316
t: plaintext,
288-
f: attachedFilename,
289-
d: fileDataB64
317+
files: filesArr
290318
});
291319
} else {
292320
envelope = JSON.stringify({ t: plaintext });
@@ -299,8 +327,8 @@
299327
);
300328
const full = new Uint8Array([...iv, ...new Uint8Array(ctBuf)]);
301329
document.getElementById('ciphertext').value = bufToB64(full);
302-
attachedFile = null;
303-
attachedFilename = "";
330+
attachedFiles = [];
331+
updateAttachedFilesList();
304332
document.getElementById('fileInput').value = "";
305333
document.getElementById('downloadAttachedBtn').style.display = "none";
306334
showTabContent('tab2');
@@ -328,14 +356,16 @@
328356
throw new Error('Corrupted decrypted data');
329357
}
330358
document.getElementById('plaintext').value = envelope.t || "";
331-
if (envelope.f && envelope.d) {
332-
lastDecryptedFile = base64ToUint8Array(envelope.d);
333-
lastDecryptedFilename = envelope.f;
359+
lastDecryptedFiles = [];
360+
if (envelope.files && Array.isArray(envelope.files) && envelope.files.length > 0) {
361+
lastDecryptedFiles = envelope.files.map(f => ({
362+
name: f.n,
363+
data: base64ToUint8Array(f.d)
364+
}));
334365
document.getElementById('downloadAttachedBtn').style.display = "inline";
335366
} else {
336-
lastDecryptedFile = null;
337-
lastDecryptedFilename = "";
338367
document.getElementById('downloadAttachedBtn').style.display = "none";
368+
lastDecryptedFiles = [];
339369
}
340370
showTabContent('tab1');
341371
} catch {
@@ -344,18 +374,44 @@
344374
}
345375

346376
function downloadAttachedFile() {
347-
if (!lastDecryptedFile || !lastDecryptedFilename) return;
348-
const blob = new Blob([lastDecryptedFile]);
349-
const url = URL.createObjectURL(blob);
350-
const a = document.createElement('a');
351-
a.href = url;
352-
a.download = lastDecryptedFilename;
353-
document.body.appendChild(a);
354-
a.click();
355-
setTimeout(() => {
356-
document.body.removeChild(a);
357-
URL.revokeObjectURL(url);
358-
}, 100);
377+
if (!lastDecryptedFiles.length) return;
378+
if (lastDecryptedFiles.length === 1) {
379+
const blob = new Blob([lastDecryptedFiles[0].data]);
380+
const url = URL.createObjectURL(blob);
381+
const a = document.createElement('a');
382+
a.href = url;
383+
a.download = lastDecryptedFiles[0].name;
384+
document.body.appendChild(a);
385+
a.click();
386+
setTimeout(() => {
387+
document.body.removeChild(a);
388+
URL.revokeObjectURL(url);
389+
}, 100);
390+
} else {
391+
const zipName = "attachments.zip";
392+
createAndDownloadZip(lastDecryptedFiles, zipName);
393+
}
394+
}
395+
396+
function createAndDownloadZip(files, zipName) {
397+
if (typeof JSZip === "undefined") {
398+
alert("Multiple file download requires JSZip library.");
399+
return;
400+
}
401+
const zip = new JSZip();
402+
files.forEach(f => zip.file(f.name, f.data));
403+
zip.generateAsync({ type: "blob" }).then(blob => {
404+
const url = URL.createObjectURL(blob);
405+
const a = document.createElement('a');
406+
a.href = url;
407+
a.download = zipName;
408+
document.body.appendChild(a);
409+
a.click();
410+
setTimeout(() => {
411+
document.body.removeChild(a);
412+
URL.revokeObjectURL(url);
413+
}, 100);
414+
});
359415
}
360416

361417
function showTabContent(tabId) {
@@ -370,4 +426,5 @@
370426
}
371427
}
372428
</script>
429+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
373430
</html>

0 commit comments

Comments
 (0)