From 5c519a15c24e5c913112a4dc0504836f2d108bb2 Mon Sep 17 00:00:00 2001 From: Hagen Fritsch Date: Sun, 26 Feb 2023 19:50:19 +0100 Subject: [PATCH] Fix body.html for larger files and UTF-8 contents. --- extension/background.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/extension/background.js b/extension/background.js index 1655d5a..93933f2 100644 --- a/extension/background.js +++ b/extension/background.js @@ -61,6 +61,26 @@ const utf8ArrayToString = (function() { return utf8 => decoder.decode(utf8); })(); +// btoa cannot be used on Uint8Arrays or strings containing utf8 characters. +// This is the best solution per https://stackoverflow.com/a/66046176 +const utf8ArrayToBase64 = async (data) => { + if(data.length == 0) return ''; + + // Use a FileReader to generate a base64 data URI + const base64url = await new Promise((r) => { + const reader = new FileReader() + reader.onload = () => r(reader.result) + reader.readAsDataURL(new Blob([data])) + }); + + /* + The result looks like + "data:application/octet-stream;base64,", + so we split off the beginning: + */ + return base64url.split(",", 2)[1] +}; + // global so it can be hot-reloaded window.Routes = {}; @@ -127,7 +147,7 @@ const makeRouteWithContents = (function() { return { fh: Cache.storeObject(req.path, toUtf8Array(data)) }; }, async read({fh, size, offset}) { - return { buf: String.fromCharCode(...Cache.getObjectForHandle(fh).slice(offset, offset + size)) }; + return { buf: Cache.getObjectForHandle(fh).slice(offset, offset + size) }; }, async write(req) { const {fh, offset, buf} = req; @@ -919,7 +939,13 @@ async function onMessage(req) { const [route, vars] = tryMatchRoute(req.path); response = await route[req.op]({...req, ...vars}); response.op = req.op; - if (response.buf) { response.buf = btoa(response.buf); } + if (response.buf) { + if (response.buf instanceof Uint8Array) { + response.buf = await utf8ArrayToBase64(response.buf); + } else { + response.buf = btoa(response.buf); + } + } } catch (e) { console.error(e);