From ac2f743b76b92c46624cab87cd0f6630256738e4 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Wed, 6 May 2020 19:25:56 -0400 Subject: [PATCH] Remove invalid file name characters from Anki media files (#496) * Replace invalid file name characters * Replace "filename" with "fileName" --- ext/bg/js/anki-note-builder.js | 33 ++++++++++++++++++++------------- ext/bg/js/anki.js | 4 ++-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index 1f9c6ed2..76199db7 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -76,8 +76,9 @@ class AnkiNoteBuilder { const expressions = definition.expressions; const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition; - const filename = this._createInjectedAudioFileName(audioSourceDefinition); - if (filename === null) { return; } + let fileName = this._createInjectedAudioFileName(audioSourceDefinition); + if (fileName === null) { return; } + fileName = AnkiNoteBuilder.replaceInvalidFileNameCharacters(fileName); const {audio} = await this._audioSystem.getDefinitionAudio( audioSourceDefinition, @@ -91,9 +92,9 @@ class AnkiNoteBuilder { ); const data = AnkiNoteBuilder.arrayBufferToBase64(audio); - await this._anki.storeMediaFile(filename, data); + await this._anki.storeMediaFile(fileName, data); - definition.audioFileName = filename; + definition.audioFileName = fileName; } catch (e) { // NOP } @@ -103,28 +104,29 @@ class AnkiNoteBuilder { if (!this._containsMarker(fields, 'screenshot')) { return; } const now = new Date(Date.now()); - const filename = `yomichan_browser_screenshot_${definition.reading}_${this._dateToString(now)}.${screenshot.format}`; + let fileName = `yomichan_browser_screenshot_${definition.reading}_${this._dateToString(now)}.${screenshot.format}`; + fileName = AnkiNoteBuilder.replaceInvalidFileNameCharacters(fileName); const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, ''); try { - await this._anki.storeMediaFile(filename, data); + await this._anki.storeMediaFile(fileName, data); } catch (e) { return; } - definition.screenshotFileName = filename; + definition.screenshotFileName = fileName; } _createInjectedAudioFileName(definition) { const {reading, expression} = definition; if (!reading && !expression) { return null; } - let filename = 'yomichan'; - if (reading) { filename += `_${reading}`; } - if (expression) { filename += `_${expression}`; } - filename += '.mp3'; - filename = filename.replace(/\]/g, ''); - return filename; + let fileName = 'yomichan'; + if (reading) { fileName += `_${reading}`; } + if (expression) { fileName += `_${expression}`; } + fileName += '.mp3'; + fileName = fileName.replace(/\]/g, ''); + return fileName; } _dateToString(date) { @@ -147,6 +149,11 @@ class AnkiNoteBuilder { return false; } + static replaceInvalidFileNameCharacters(fileName) { + // eslint-disable-next-line no-control-regex + return fileName.replace(/[<>:"/\\|?*\x00-\x1F]/g, '-'); + } + static arrayBufferToBase64(arrayBuffer) { return window.btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))); } diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index 0d38837c..55953007 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -79,12 +79,12 @@ class AnkiConnect { return await this._invoke('guiBrowse', {query}); } - async storeMediaFile(filename, dataBase64) { + async storeMediaFile(fileName, dataBase64) { if (!this._enabled) { throw new Error('AnkiConnect not enabled'); } await this._checkVersion(); - return await this._invoke('storeMediaFile', {filename, data: dataBase64}); + return await this._invoke('storeMediaFile', {filename: fileName, data: dataBase64}); } async findNoteIds(notes, duplicateScope) {