get import maps working, add JSDoc ish to modules, let EJS import them
This commit is contained in:
110
static/js/send.js
Normal file
110
static/js/send.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import { HexMix } from "/utils";
|
||||
|
||||
/**
|
||||
* Initializes the send page functionality.
|
||||
* This function sets up event listeners and handles the form submission process.
|
||||
*/
|
||||
export function initializeSendPage() {
|
||||
const copyButton = document.getElementById("copyButton");
|
||||
const fileInput = document.getElementById("file");
|
||||
const form = document.getElementById("secretForm");
|
||||
const resultInput = document.getElementById("result");
|
||||
const encryptedDataTextarea = document.getElementById("encryptedData");
|
||||
|
||||
/**
|
||||
* Copies the result URL to the clipboard.
|
||||
*/
|
||||
copyButton.addEventListener("click", async () => {
|
||||
resultInput.select();
|
||||
await navigator.clipboard.writeText(resultInput.value);
|
||||
alert("URL copied to clipboard!");
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggles the text input based on file selection.
|
||||
* @param {Event} e - The change event.
|
||||
*/
|
||||
fileInput.addEventListener("change", (e) => {
|
||||
const file = e.target.files[0];
|
||||
document.getElementById("text").disabled = !!file;
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles the form submission.
|
||||
* @param {Event} e - The submit event.
|
||||
*/
|
||||
form.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(form);
|
||||
const text = formData.get("text");
|
||||
const file = formData.get("file");
|
||||
const serviceIdentifier = formData.get("serviceIdentifier");
|
||||
const service = formData.get("service");
|
||||
|
||||
let plaintext = text;
|
||||
let filetype = "text/plain";
|
||||
let filename = "secret.txt";
|
||||
|
||||
if (file.size > 0) {
|
||||
if (file.size > 2097152) {
|
||||
alert("Error: Max file size is 2mb.");
|
||||
return;
|
||||
}
|
||||
plaintext = await file.arrayBuffer();
|
||||
filetype = file.type;
|
||||
filename = file.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new AES-GCM key.
|
||||
* @type {CryptoKey}
|
||||
*/
|
||||
const key = await window.crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
|
||||
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const exported = await window.crypto.subtle.exportKey("raw", key);
|
||||
|
||||
/**
|
||||
* Encrypts the plaintext.
|
||||
* @type {ArrayBuffer}
|
||||
*/
|
||||
const encrypted = await window.crypto.subtle.encrypt(
|
||||
{ name: "AES-GCM", iv },
|
||||
key,
|
||||
typeof plaintext === "string" ? HexMix.stringToArrayBuffer(plaintext) : plaintext
|
||||
);
|
||||
|
||||
// Convert the encrypted ArrayBuffer to a Base64 string
|
||||
const encryptedBase64 = HexMix.arrayBufferToBase64(encrypted);
|
||||
encryptedDataTextarea.value = encryptedBase64;
|
||||
|
||||
const keyHex = HexMix.uint8ToHex(new Uint8Array(exported));
|
||||
const ivHex = HexMix.uint8ToHex(iv);
|
||||
const keyParams = { key: keyHex, iv: ivHex };
|
||||
|
||||
const params = JSON.stringify({
|
||||
service: service,
|
||||
serviceIdentifier: serviceIdentifier,
|
||||
text: encryptedBase64,
|
||||
iv: ivHex,
|
||||
filetype: filetype,
|
||||
filename: filename
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch("/rest/links", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: params
|
||||
});
|
||||
const data = await response.json();
|
||||
const url = `http://${window.location.host}/rest/links/${data.id}#${btoa(JSON.stringify(keyParams))}`;
|
||||
resultInput.value = url;
|
||||
} catch (err) {
|
||||
alert(`Error: ${err.message}`);
|
||||
}
|
||||
});
|
||||
}
|
46
static/js/utils.js
Normal file
46
static/js/utils.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Utility object for handling hexadecimal and binary data conversions.
|
||||
* @namespace
|
||||
*/
|
||||
export const HexMix = {
|
||||
/**
|
||||
* Converts a Uint8Array to a hexadecimal string.
|
||||
* @param {Uint8Array} data - The input Uint8Array.
|
||||
* @returns {string} The hexadecimal representation of the input data.
|
||||
*/
|
||||
uint8ToHex(data) {
|
||||
return Array.from(data, (byte) => ("00" + byte.toString(16)).slice(-2)).join("");
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hexadecimal string to a Uint8Array.
|
||||
* @param {string} data - The input hexadecimal string.
|
||||
* @returns {Uint8Array} The Uint8Array representation of the input data.
|
||||
*/
|
||||
hexToUint8(data) {
|
||||
const hexArray = data.match(/.{1,2}/g);
|
||||
return hexArray ? new Uint8Array(hexArray.map((char) => parseInt(char, 16))) : new Uint8Array(0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an ArrayBuffer to a Base64 string.
|
||||
* @param {ArrayBuffer} buf - The input ArrayBuffer.
|
||||
* @returns {string} The Base64 representation of the input data.
|
||||
*/
|
||||
arrayBufferToBase64(buf) {
|
||||
return btoa(String.fromCharCode.apply(null, new Uint8Array(buf)));
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a string to an ArrayBuffer.
|
||||
* @param {string} str - The input string.
|
||||
* @returns {ArrayBuffer} The ArrayBuffer representation of the input string.
|
||||
*/
|
||||
stringToArrayBuffer(str) {
|
||||
const array = new Uint8Array(str.length);
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
array[i] = str.charCodeAt(i);
|
||||
}
|
||||
return array.buffer;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user