Skip to content

Commit dcb9d7f

Browse files
committed
Copy file function updates from Parchment:
parse_base64 chunks its input when longer than 30MB, fixes curiousdannii/parchment#157 Improve caching of IF Archive files (curiousdannii/parchment#149)
1 parent 755ab4d commit dcb9d7f

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

src/common/file.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,24 @@ https://github.com/curiousdannii/asyncglk
1212
export type ProgressCallback = (bytes: number) => void
1313

1414
/** Parse Base 64 into a Uint8Array */
15-
export async function parse_base64(data: string, data_type = 'octet-binary'): Promise<Uint8Array> {
15+
export async function parse_base64(data: string): Promise<Uint8Array> {
16+
// Firefox has a data URL limit of 32MB, so we have to chunk large data
17+
const chunk_length = 30_000_000
18+
if (data.length < chunk_length) {
19+
return parse_base64_with_data_url(data)
20+
}
21+
const chunks: Uint8Array[] = []
22+
let i = 0
23+
while (i < data.length) {
24+
chunks.push(await parse_base64_with_data_url(data.substring(i, i += chunk_length)))
25+
}
26+
const blob = new Blob(chunks)
27+
return new Uint8Array(await blob.arrayBuffer())
28+
}
29+
30+
async function parse_base64_with_data_url(data: string) {
1631
// Parse base64 using a trick from https://stackoverflow.com/a/54123275/2854284
17-
const response = await fetch(`data:application/${data_type};base64,${data}`)
32+
const response = await fetch(`data:application/octet-stream;base64,${data}`)
1833
if (!response.ok) {
1934
throw new Error(`Could not parse base64: ${response.status}`)
2035
}

src/dialog/browser/download.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export async function fetch_storyfile(options: DownloadOptions, url: string, pro
7979
// Handle a relative URL
8080
const story_url = new URL(url, document.URL)
8181
const story_domain = story_url.hostname
82+
const same_protocol = story_url.protocol === document.location.protocol
8283
const same_domain = story_domain === document.location.hostname
8384
const proxy_url = `${options.proxy_url}?url=${story_url}`
8485
let response: Response
@@ -90,10 +91,12 @@ export async function fetch_storyfile(options: DownloadOptions, url: string, pro
9091
}
9192

9293
// Only directly access files same origin files or those from the list of reliable domains
93-
let direct_access = same_domain || story_url.protocol === 'data:'
94+
let direct_access = (same_protocol && same_domain) || story_url.protocol === 'data:'
9495
if (!direct_access) {
9596
for (const domain of options.direct_domains) {
9697
if (story_domain.endsWith(domain)) {
98+
// all direct domains require HTTPS
99+
story_url.protocol = 'https:'
97100
direct_access = true
98101
break
99102
}

0 commit comments

Comments
 (0)