From cf7b6b2515ef6e1d37e251656bf8b201453de336 Mon Sep 17 00:00:00 2001 From: Chris Midgley Date: Mon, 28 Feb 2022 20:27:56 +0000 Subject: [PATCH] web: Don't include query parameters in downloaded SWF name (#6368) * fix: don't include query parameters in downloaded SWF name * refactor: store swfUrl as URL --- web/packages/core/src/ruffle-player.ts | 23 +++++++---------------- web/packages/core/src/swf-file-name.ts | 11 +++++++++++ web/packages/core/test/swf-file-name.ts | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 web/packages/core/src/swf-file-name.ts create mode 100644 web/packages/core/test/swf-file-name.ts diff --git a/web/packages/core/src/ruffle-player.ts b/web/packages/core/src/ruffle-player.ts index b93ffd464..ee72f2ff5 100644 --- a/web/packages/core/src/ruffle-player.ts +++ b/web/packages/core/src/ruffle-player.ts @@ -13,6 +13,7 @@ import { } from "./load-options"; import { MovieMetadata } from "./movie-metadata"; import { InternalContextMenuItem } from "./context-menu"; +import { swfFileName } from "./swf-file-name"; export const FLASH_MIMETYPE = "application/x-shockwave-flash"; export const FUTURESPLASH_MIMETYPE = "application/futuresplash"; @@ -131,7 +132,7 @@ export class RufflePlayer extends HTMLElement { // Set to true when a touch event is encountered. private isTouch = false; - private swfUrl?: string; + private swfUrl?: URL; private instance: Ruffle | null; private options: BaseLoadOptions | null; private lastActivePlayingState: boolean; @@ -577,14 +578,7 @@ export class RufflePlayer extends HTMLElement { if ("url" in options) { console.log(`Loading SWF file ${options.url}`); - try { - this.swfUrl = new URL( - options.url, - document.location.href - ).href; - } catch { - this.swfUrl = options.url; - } + this.swfUrl = new URL(options.url, document.location.href); const parameters = { ...sanitizeParameters( @@ -593,7 +587,7 @@ export class RufflePlayer extends HTMLElement { ...sanitizeParameters(options.parameters), }; - this.instance!.stream_from(this.swfUrl, parameters); + this.instance!.stream_from(this.swfUrl.href, parameters); } else if ("data" in options) { console.log("Loading SWF data"); this.instance!.load_data( @@ -723,7 +717,7 @@ export class RufflePlayer extends HTMLElement { try { if (this.swfUrl) { console.log("Downloading SWF: " + this.swfUrl); - const response = await fetch(this.swfUrl); + const response = await fetch(this.swfUrl.href); if (!response.ok) { console.error("SWF download failed"); return; @@ -733,9 +727,7 @@ export class RufflePlayer extends HTMLElement { const swfDownloadA = document.createElement("a"); swfDownloadA.style.display = "none"; swfDownloadA.href = blobUrl; - swfDownloadA.download = this.swfUrl.substring( - this.swfUrl.lastIndexOf("/") + 1 - ); + swfDownloadA.download = swfFileName(this.swfUrl); document.body.appendChild(swfDownloadA); swfDownloadA.click(); document.body.removeChild(swfDownloadA); @@ -1316,9 +1308,8 @@ export class RufflePlayer extends HTMLElement { } displayRootMovieDownloadFailedMessage(): void { - const swfUrl = new URL(this.swfUrl!); if ( - window.location.origin == swfUrl.origin || + window.location.origin == this.swfUrl!.origin || !this.isExtension || !window.location.protocol.includes("http") ) { diff --git a/web/packages/core/src/swf-file-name.ts b/web/packages/core/src/swf-file-name.ts new file mode 100644 index 000000000..5dabfc91c --- /dev/null +++ b/web/packages/core/src/swf-file-name.ts @@ -0,0 +1,11 @@ +/** + * Create a filename to save a downloaded SWF into. + * + * @param swfUrl The URL of the SWF file. + * @returns The filename the SWF file can be saved at. + */ +export function swfFileName(swfUrl: URL): string { + const pathName = swfUrl.pathname; + const name = pathName.substring(pathName.lastIndexOf("/") + 1); + return name; +} diff --git a/web/packages/core/test/swf-file-name.ts b/web/packages/core/test/swf-file-name.ts new file mode 100644 index 000000000..897c01544 --- /dev/null +++ b/web/packages/core/test/swf-file-name.ts @@ -0,0 +1,20 @@ +import { strict as assert } from "assert"; +import { swfFileName } from "../src/swf-file-name"; + +describe("swfFileName", function () { + it("should extract simple SWF name", function () { + assert.deepEqual(nameFor("http://example.com/file.swf"), "file.swf"); + }); + it("should not include query parameters", function () { + assert.deepEqual( + nameFor( + "https://uploads.ungrounded.net/574000/574241_DiamondNGSP.swf?123" + ), + "574241_DiamondNGSP.swf" + ); + }); +}); + +function nameFor(url: string): string { + return swfFileName(new URL(url)); +}