From 10a429c68db96f8d7fff55421712afb22f6bb2db Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Oct 2022 19:54:10 -0600 Subject: [PATCH] Include a file-safe room name and ISO date in chat exports (#9440) * conversation export named after room * sanitization added for exported file name * sanitization added for exported file name * sanitization added for exported file name * sanitization added for exported file name=>lint error fixed * sanitization added for exported file name=>lint error fixed * sanitization added for exported file name=>redundancy removed * sanitization added for exported file name=>redundancy removed * reverted to previous commit * sanitization added for exported file name=>redundancy removed * exported chat date iso formatted * conversation export named after room * conversation export named after room Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * code refacto filename date format * Add docs to fn * Bring in a util library for sanitizing * Extract file naming function and make consistent for all 3 types Also use the library we dragged in * Write tests & associated fixes * Apply linters locally * Include new date util in index Co-authored-by: Sinharitik589 Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: yaya-usman Co-authored-by: Sinharitik589 <67551927+Sinharitik589@users.noreply.github.com> --- package.json | 1 + src/DateUtils.ts | 11 +++ src/i18n/strings/en_EN.json | 2 +- src/utils/exportUtils/Exporter.ts | 24 ++++- src/utils/exportUtils/JSONExport.ts | 10 +- src/utils/exportUtils/PlainTextExport.ts | 9 +- test/test-utils/date.ts | 17 ++++ test/test-utils/index.ts | 1 + test/utils/DateUtils-test.ts | 9 +- test/utils/exportUtils/HTMLExport-test.ts | 52 ++++++++++ test/utils/exportUtils/JSONExport-test.ts | 39 ++++++++ .../utils/exportUtils/PlainTextExport-test.ts | 39 ++++++++ .../__snapshots__/HTMLExport-test.ts.snap | 5 + .../__snapshots__/JSONExport-test.ts.snap | 3 + .../PlainTextExport-test.ts.snap | 3 + yarn.lock | 98 ++++--------------- 16 files changed, 233 insertions(+), 90 deletions(-) create mode 100644 test/test-utils/date.ts create mode 100644 test/utils/exportUtils/HTMLExport-test.ts create mode 100644 test/utils/exportUtils/JSONExport-test.ts create mode 100644 test/utils/exportUtils/PlainTextExport-test.ts create mode 100644 test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap create mode 100644 test/utils/exportUtils/__snapshots__/JSONExport-test.ts.snap create mode 100644 test/utils/exportUtils/__snapshots__/PlainTextExport-test.ts.snap diff --git a/package.json b/package.json index 82ec05f81a..b203cf51e9 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "react-focus-lock": "^2.5.1", "react-transition-group": "^4.4.1", "rfc4648": "^1.4.0", + "sanitize-filename": "^1.6.3", "sanitize-html": "^2.3.2", "tar-js": "^0.3.0", "ua-parser-js": "^1.0.2", diff --git a/src/DateUtils.ts b/src/DateUtils.ts index 20227354f0..2b50bddb85 100644 --- a/src/DateUtils.ts +++ b/src/DateUtils.ts @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd +Copyright 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -177,6 +178,16 @@ export function formatFullDateNoDay(date: Date) { }); } +/** + * Returns an ISO date string without textual description of the date (ie: no "Wednesday" or + * similar) + * @param date The date to format. + * @returns The date string in ISO format. + */ +export function formatFullDateNoDayISO(date: Date): string { + return date.toISOString(); +} + export function formatFullDateNoDayNoTime(date: Date) { return ( date.getFullYear() + diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index fa0b1690dc..ca804ea50b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -756,6 +756,7 @@ "Zoom in": "Zoom in", "Zoom out": "Zoom out", "Are you sure you want to exit during this export?": "Are you sure you want to exit during this export?", + "Unnamed Room": "Unnamed Room", "Generating a ZIP": "Generating a ZIP", "Fetched %(count)s events out of %(total)s|other": "Fetched %(count)s events out of %(total)s", "Fetched %(count)s events out of %(total)s|one": "Fetched %(count)s event out of %(total)s", @@ -2768,7 +2769,6 @@ "Or send invite link": "Or send invite link", "Unnamed Space": "Unnamed Space", "Invite to %(roomName)s": "Invite to %(roomName)s", - "Unnamed Room": "Unnamed Room", "Invite someone using their name, email address, username (like ) or share this space.": "Invite someone using their name, email address, username (like ) or share this space.", "Invite someone using their name, username (like ) or share this space.": "Invite someone using their name, username (like ) or share this space.", "Invite someone using their name, email address, username (like ) or share this room.": "Invite someone using their name, email address, username (like ) or share this room.", diff --git a/src/utils/exportUtils/Exporter.ts b/src/utils/exportUtils/Exporter.ts index 7f7f57f92e..ec20f395e3 100644 --- a/src/utils/exportUtils/Exporter.ts +++ b/src/utils/exportUtils/Exporter.ts @@ -1,5 +1,5 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,12 +20,13 @@ import { MatrixClient } from "matrix-js-sdk/src/client"; import { Direction } from "matrix-js-sdk/src/models/event-timeline"; import { saveAs } from "file-saver"; import { logger } from "matrix-js-sdk/src/logger"; +import sanitizeFilename from "sanitize-filename"; import { MatrixClientPeg } from "../../MatrixClientPeg"; import { ExportType, IExportOptions } from "./exportUtils"; import { decryptFile } from "../DecryptFile"; import { mediaFromContent } from "../../customisations/Media"; -import { formatFullDateNoDay } from "../../DateUtils"; +import { formatFullDateNoDay, formatFullDateNoDayISO } from "../../DateUtils"; import { isVoiceMessage } from "../EventUtils"; import { IMediaEventContent } from "../../customisations/models/IMediaEventContent"; import { _t } from "../../languageHandler"; @@ -57,6 +58,10 @@ export default abstract class Exporter { window.addEventListener("beforeunload", this.onBeforeUnload); } + public get destinationFileName(): string { + return this.makeFileNameNoExtension(SdkConfig.get().brand) + ".zip"; + } + protected onBeforeUnload(e: BeforeUnloadEvent): string { e.preventDefault(); return e.returnValue = _t("Are you sure you want to exit during this export?"); @@ -75,10 +80,19 @@ export default abstract class Exporter { this.files.push(file); } + protected makeFileNameNoExtension(brand = "matrix"): string { + // First try to use the real name of the room, then a translated copy of a generic name, + // then finally hardcoded default to guarantee we'll have a name. + const safeRoomName = sanitizeFilename(this.room.name ?? _t("Unnamed Room")).trim() || "Unnamed Room"; + const safeDate = formatFullDateNoDayISO(new Date()) + .replace(/:/g, '-'); // ISO format automatically removes a lot of stuff for us + const safeBrand = sanitizeFilename(brand); + return `${safeBrand} - ${safeRoomName} - Chat Export - ${safeDate}`; + } + protected async downloadZIP(): Promise { - const brand = SdkConfig.get().brand; - const filenameWithoutExt = `${brand} - Chat Export - ${formatFullDateNoDay(new Date())}`; - const filename = `${filenameWithoutExt}.zip`; + const filename = this.destinationFileName; + const filenameWithoutExt = filename.substring(0, filename.length - 4); // take off the .zip const { default: JSZip } = await import('jszip'); const zip = new JSZip(); diff --git a/src/utils/exportUtils/JSONExport.ts b/src/utils/exportUtils/JSONExport.ts index b0b4b330b0..a0dc5e036e 100644 --- a/src/utils/exportUtils/JSONExport.ts +++ b/src/utils/exportUtils/JSONExport.ts @@ -1,5 +1,5 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import { EventType } from "matrix-js-sdk/src/@types/event"; import { logger } from "matrix-js-sdk/src/logger"; import Exporter from "./Exporter"; -import { formatFullDateNoDay, formatFullDateNoDayNoTime } from "../../DateUtils"; +import { formatFullDateNoDayNoTime } from "../../DateUtils"; import { ExportType, IExportOptions } from "./exportUtils"; import { _t } from "../../languageHandler"; import { haveRendererForEvent } from "../../events/EventTileFactory"; @@ -38,6 +38,10 @@ export default class JSONExporter extends Exporter { super(room, exportType, exportOptions, setProgressText); } + public get destinationFileName(): string { + return this.makeFileNameNoExtension() + ".json"; + } + protected createJSONString(): string { const exportDate = formatFullDateNoDayNoTime(new Date()); const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender(); @@ -108,7 +112,7 @@ export default class JSONExporter extends Exporter { this.addFile("export.json", new Blob([text])); await this.downloadZIP(); } else { - const fileName = `matrix-export-${formatFullDateNoDay(new Date())}.json`; + const fileName = this.destinationFileName; this.downloadPlainText(fileName, text); } diff --git a/src/utils/exportUtils/PlainTextExport.ts b/src/utils/exportUtils/PlainTextExport.ts index cc4cad1894..3150b15c64 100644 --- a/src/utils/exportUtils/PlainTextExport.ts +++ b/src/utils/exportUtils/PlainTextExport.ts @@ -1,5 +1,5 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import { logger } from "matrix-js-sdk/src/logger"; import React from "react"; import Exporter from "./Exporter"; -import { formatFullDateNoDay } from "../../DateUtils"; import { _t } from "../../languageHandler"; import { ExportType, IExportOptions } from "./exportUtils"; import { textForEvent } from "../../TextForEvent"; @@ -43,6 +42,10 @@ export default class PlainTextExporter extends Exporter { : _t("Media omitted - file size limit exceeded"); } + public get destinationFileName(): string { + return this.makeFileNameNoExtension() + ".txt"; + } + public textForReplyEvent = (content: IContent) => { const REPLY_REGEX = /> <(.*?)>(.*?)\n\n(.*)/s; const REPLY_SOURCE_MAX_LENGTH = 32; @@ -137,7 +140,7 @@ export default class PlainTextExporter extends Exporter { this.addFile("export.txt", new Blob([text])); await this.downloadZIP(); } else { - const fileName = `matrix-export-${formatFullDateNoDay(new Date())}.txt`; + const fileName = this.destinationFileName; this.downloadPlainText(fileName, text); } diff --git a/test/test-utils/date.ts b/test/test-utils/date.ts new file mode 100644 index 0000000000..c3010b2ae9 --- /dev/null +++ b/test/test-utils/date.ts @@ -0,0 +1,17 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export const REPEATABLE_DATE = new Date(2022, 10, 17, 16, 58, 32, 517); diff --git a/test/test-utils/index.ts b/test/test-utils/index.ts index 959b41352b..2fa87e1e67 100644 --- a/test/test-utils/index.ts +++ b/test/test-utils/index.ts @@ -24,3 +24,4 @@ export * from './test-utils'; export * from './call'; export * from './wrappers'; export * from './utilities'; +export * from './date'; diff --git a/test/utils/DateUtils-test.ts b/test/utils/DateUtils-test.ts index 7804fd6e9c..784be85ea7 100644 --- a/test/utils/DateUtils-test.ts +++ b/test/utils/DateUtils-test.ts @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { formatSeconds, formatRelativeTime, formatDuration } from "../../src/DateUtils"; +import { formatSeconds, formatRelativeTime, formatDuration, formatFullDateNoDayISO } from "../../src/DateUtils"; +import { REPEATABLE_DATE } from "../test-utils"; describe("formatSeconds", () => { it("correctly formats time with hours", () => { @@ -92,3 +93,9 @@ describe('formatDuration()', () => { expect(formatDuration(input)).toEqual(expectedResult); }); }); + +describe("formatFullDateNoDayISO", () => { + it("should return ISO format", () => { + expect(formatFullDateNoDayISO(REPEATABLE_DATE)).toEqual("2022-11-17T16:58:32.517Z"); + }); +}); diff --git a/test/utils/exportUtils/HTMLExport-test.ts b/test/utils/exportUtils/HTMLExport-test.ts new file mode 100644 index 0000000000..e009205d8d --- /dev/null +++ b/test/utils/exportUtils/HTMLExport-test.ts @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { mocked } from "jest-mock"; + +import { createTestClient, mkStubRoom, REPEATABLE_DATE } from "../../test-utils"; +import { ExportType, IExportOptions } from "../../../src/utils/exportUtils/exportUtils"; +import SdkConfig from "../../../src/SdkConfig"; +import HTMLExporter from "../../../src/utils/exportUtils/HtmlExport"; + +describe("HTMLExport", () => { + beforeEach(() => { + jest.useFakeTimers('modern'); + jest.setSystemTime(REPEATABLE_DATE); + }); + + afterEach(() => { + mocked(SdkConfig.get).mockRestore(); + }); + + it("should have an SDK-branded destination file name", () => { + const roomName = "My / Test / Room: Welcome"; + const client = createTestClient(); + const stubOptions: IExportOptions = { + attachmentsIncluded: false, + maxSize: 50000000, + }; + const stubRoom = mkStubRoom("!myroom:example.org", roomName, client); + const exporter = new HTMLExporter(stubRoom, ExportType.Timeline, stubOptions, () => {}); + + expect(exporter.destinationFileName).toMatchSnapshot(); + + jest.spyOn(SdkConfig, "get").mockImplementation(() => { + return { brand: "BrandedChat/WithSlashes/ForFun" }; + }); + + expect(exporter.destinationFileName).toMatchSnapshot(); + }); +}); diff --git a/test/utils/exportUtils/JSONExport-test.ts b/test/utils/exportUtils/JSONExport-test.ts new file mode 100644 index 0000000000..3f161a23ea --- /dev/null +++ b/test/utils/exportUtils/JSONExport-test.ts @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import JSONExporter from "../../../src/utils/exportUtils/JSONExport"; +import { createTestClient, mkStubRoom, REPEATABLE_DATE } from "../../test-utils"; +import { ExportType, IExportOptions } from "../../../src/utils/exportUtils/exportUtils"; + +describe("JSONExport", () => { + beforeEach(() => { + jest.useFakeTimers('modern'); + jest.setSystemTime(REPEATABLE_DATE); + }); + + it("should have a Matrix-branded destination file name", () => { + const roomName = "My / Test / Room: Welcome"; + const client = createTestClient(); + const stubOptions: IExportOptions = { + attachmentsIncluded: false, + maxSize: 50000000, + }; + const stubRoom = mkStubRoom("!myroom:example.org", roomName, client); + const exporter = new JSONExporter(stubRoom, ExportType.Timeline, stubOptions, () => {}); + + expect(exporter.destinationFileName).toMatchSnapshot(); + }); +}); diff --git a/test/utils/exportUtils/PlainTextExport-test.ts b/test/utils/exportUtils/PlainTextExport-test.ts new file mode 100644 index 0000000000..919eb40cfa --- /dev/null +++ b/test/utils/exportUtils/PlainTextExport-test.ts @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { createTestClient, mkStubRoom, REPEATABLE_DATE } from "../../test-utils"; +import { ExportType, IExportOptions } from "../../../src/utils/exportUtils/exportUtils"; +import PlainTextExporter from "../../../src/utils/exportUtils/PlainTextExport"; + +describe("PlainTextExport", () => { + beforeEach(() => { + jest.useFakeTimers('modern'); + jest.setSystemTime(REPEATABLE_DATE); + }); + + it("should have a Matrix-branded destination file name", () => { + const roomName = "My / Test / Room: Welcome"; + const client = createTestClient(); + const stubOptions: IExportOptions = { + attachmentsIncluded: false, + maxSize: 50000000, + }; + const stubRoom = mkStubRoom("!myroom:example.org", roomName, client); + const exporter = new PlainTextExporter(stubRoom, ExportType.Timeline, stubOptions, () => {}); + + expect(exporter.destinationFileName).toMatchSnapshot(); + }); +}); diff --git a/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap b/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap new file mode 100644 index 0000000000..5cfed9ef90 --- /dev/null +++ b/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`HTMLExport should have an SDK-branded destination file name 1`] = `"Element - My Test Room Welcome - Chat Export - 2022-11-17T16-58-32.517Z.zip"`; + +exports[`HTMLExport should have an SDK-branded destination file name 2`] = `"BrandedChatWithSlashesForFun - My Test Room Welcome - Chat Export - 2022-11-17T16-58-32.517Z.zip"`; diff --git a/test/utils/exportUtils/__snapshots__/JSONExport-test.ts.snap b/test/utils/exportUtils/__snapshots__/JSONExport-test.ts.snap new file mode 100644 index 0000000000..5f0d78cc58 --- /dev/null +++ b/test/utils/exportUtils/__snapshots__/JSONExport-test.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`JSONExport should have a Matrix-branded destination file name 1`] = `"matrix - My Test Room Welcome - Chat Export - 2022-11-17T16-58-32.517Z.json"`; diff --git a/test/utils/exportUtils/__snapshots__/PlainTextExport-test.ts.snap b/test/utils/exportUtils/__snapshots__/PlainTextExport-test.ts.snap new file mode 100644 index 0000000000..ebee2957b7 --- /dev/null +++ b/test/utils/exportUtils/__snapshots__/PlainTextExport-test.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PlainTextExport should have a Matrix-branded destination file name 1`] = `"matrix - My Test Room Welcome - Chat Export - 2022-11-17T16-58-32.517Z.txt"`; diff --git a/yarn.lock b/yarn.lock index ee6ceafdcf..b54bc1ec81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2674,7 +2674,7 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -3198,11 +3198,6 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browser-request@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" - integrity sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg== - browserslist@^4.20.2, browserslist@^4.21.3: version "4.21.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a" @@ -5285,19 +5280,6 @@ grid-index@^1.1.0: resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7" integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA== -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -5458,15 +5440,6 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - http-signature@~1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" @@ -6695,16 +6668,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - jsprim@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" @@ -7070,14 +7033,12 @@ matrix-events-sdk@^0.0.1-beta.7: dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" - browser-request "^0.3.3" bs58 "^5.0.0" content-type "^1.0.4" loglevel "^1.7.1" matrix-events-sdk "^0.0.1-beta.7" p-retry "4" qs "^6.9.6" - request "^2.88.2" unhomoglyph "^1.0.6" matrix-mock-request@^2.5.0: @@ -7396,11 +7357,6 @@ nwsapi@^2.2.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.1.tgz#10a9f268fbf4c461249ebcfe38e359aa36e2577c" integrity sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg== -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -8303,32 +8259,6 @@ request-progress@^3.0.0: dependencies: throttleit "^1.0.0" -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -8515,6 +8445,13 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sanitize-filename@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + sanitize-html@^2.3.2: version "2.7.1" resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.7.1.tgz#a6c2c1a88054a79eeacfac9b0a43f1b393476901" @@ -8788,7 +8725,7 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sshpk@^1.14.1, sshpk@^1.7.0: +sshpk@^1.14.1: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== @@ -9228,6 +9165,13 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ== + dependencies: + utf8-byte-length "^1.0.1" + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -9485,16 +9429,16 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA== + util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"