From 9d017b574503d39c46e18964c478047689bcdf43 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:46:31 +0100 Subject: [PATCH] fix: sanitize backup file names for windows --- .../javascripts/services/archiveManager.ts | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/services/archiveManager.ts b/app/assets/javascripts/services/archiveManager.ts index d80635a1d..e8f5f6de1 100644 --- a/app/assets/javascripts/services/archiveManager.ts +++ b/app/assets/javascripts/services/archiveManager.ts @@ -7,21 +7,25 @@ import { PayloadContent, } from '@standardnotes/snjs'; -function zippableTxtName(name: string, suffix = ""): string { - const sanitizedName = name - .replace(/\//g, '') - .replace(/\\+/g, '') - .replace(/:/g, ' ') - .replace(/\./g, ' '); - const nameEnd = suffix + ".txt"; +function sanitizeFileName(name: string) { + return name + .replace(/\//g, '') + .replace(/\\+/g, '') + .replace(/:/g, ' ') + .replace(/\|/g, ' ') + .replace(/\./g, ' '); +} + +function zippableTxtName(name: string, suffix = ''): string { + const sanitizedName = sanitizeFileName(name); + const nameEnd = suffix + '.txt'; const maxFileNameLength = 255; return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd; } export class ArchiveManager { - - private readonly application: WebApplication - private textFile?: string + private readonly application: WebApplication; + private textFile?: string; constructor(application: WebApplication) { this.application = application; @@ -36,10 +40,9 @@ export class ArchiveManager { if (!data) { return; } - const blobData = new Blob( - [JSON.stringify(data, null, 2)], - { type: 'text/json' } - ); + const blobData = new Blob([JSON.stringify(data, null, 2)], { + type: 'text/json', + }); if (encrypted) { this.downloadData( blobData, @@ -85,21 +88,18 @@ export class ArchiveManager { }); } - private async downloadZippedDecryptedItems( - data: BackupFile - ) { + private async downloadZippedDecryptedItems(data: BackupFile) { await this.loadZip(); const items = data.items; this.zip.createWriter( new this.zip.BlobWriter('application/zip'), async (zipWriter: any) => { await new Promise((resolve) => { - const blob = new Blob( - [JSON.stringify(data, null, 2)], - { type: 'text/plain' } - ); + const blob = new Blob([JSON.stringify(data, null, 2)], { + type: 'text/plain', + }); const fileName = zippableTxtName( - 'Standard Notes Backup and Import File.txt' + 'Standard Notes Backup and Import File' ); zipWriter.add(fileName, new this.zip.BlobReader(blob), resolve); }); @@ -120,7 +120,8 @@ export class ArchiveManager { name = ''; } const blob = new Blob([contents], { type: 'text/plain' }); - const fileName = `Items/${item.content_type}/` + + const fileName = + `Items/${sanitizeFileName(item.content_type)}/` + zippableTxtName(name, `-${item.uuid.split('-')[0]}`); zipWriter.add(fileName, new this.zip.BlobReader(blob), () => { index++; @@ -138,7 +139,9 @@ export class ArchiveManager { }); }; nextFile(); - }, onerror); + }, + onerror + ); } private hrefForData(data: Blob) {