Skip to content

Commit

Permalink
Copy file function updates from Parchment:
Browse files Browse the repository at this point in the history
parse_base64 chunks its input when longer than 30MB, fixes curiousdannii/parchment#157
Improve caching of IF Archive files (curiousdannii/parchment#149)
  • Loading branch information
curiousdannii committed Oct 26, 2024
1 parent 755ab4d commit dcb9d7f
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
19 changes: 17 additions & 2 deletions src/common/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@ https://github.com/curiousdannii/asyncglk
export type ProgressCallback = (bytes: number) => void

/** Parse Base 64 into a Uint8Array */
export async function parse_base64(data: string, data_type = 'octet-binary'): Promise<Uint8Array> {
export async function parse_base64(data: string): Promise<Uint8Array> {
// Firefox has a data URL limit of 32MB, so we have to chunk large data
const chunk_length = 30_000_000
if (data.length < chunk_length) {
return parse_base64_with_data_url(data)
}
const chunks: Uint8Array[] = []
let i = 0
while (i < data.length) {
chunks.push(await parse_base64_with_data_url(data.substring(i, i += chunk_length)))
}
const blob = new Blob(chunks)
return new Uint8Array(await blob.arrayBuffer())
}

async function parse_base64_with_data_url(data: string) {
// Parse base64 using a trick from https://stackoverflow.com/a/54123275/2854284
const response = await fetch(`data:application/${data_type};base64,${data}`)
const response = await fetch(`data:application/octet-stream;base64,${data}`)
if (!response.ok) {
throw new Error(`Could not parse base64: ${response.status}`)
}
Expand Down
5 changes: 4 additions & 1 deletion src/dialog/browser/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export async function fetch_storyfile(options: DownloadOptions, url: string, pro
// Handle a relative URL
const story_url = new URL(url, document.URL)
const story_domain = story_url.hostname
const same_protocol = story_url.protocol === document.location.protocol
const same_domain = story_domain === document.location.hostname
const proxy_url = `${options.proxy_url}?url=${story_url}`
let response: Response
Expand All @@ -90,10 +91,12 @@ export async function fetch_storyfile(options: DownloadOptions, url: string, pro
}

// Only directly access files same origin files or those from the list of reliable domains
let direct_access = same_domain || story_url.protocol === 'data:'
let direct_access = (same_protocol && same_domain) || story_url.protocol === 'data:'
if (!direct_access) {
for (const domain of options.direct_domains) {
if (story_domain.endsWith(domain)) {
// all direct domains require HTTPS
story_url.protocol = 'https:'
direct_access = true
break
}
Expand Down

0 comments on commit dcb9d7f

Please sign in to comment.