diff --git a/package.json b/package.json index 82d78d331..9016336c0 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "jest": { "testEnvironment": "jest-environment-jsdom-sixteen", "testMatch": [ - "/test/**/*-test.js" + "/test/**/*-test.[tj]s" ], "setupFilesAfterEnv": [ "/node_modules/matrix-react-sdk/test/setupTests.js" diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 8ebe47aba..c6385cc47 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -17,7 +17,6 @@ limitations under the License. // We have to trick webpack into loading our CSS for us. require("./index.scss"); -import * as qs from 'querystring'; import { KJUR } from 'jsrsasign'; import { IOpenIDCredentials, @@ -52,15 +51,16 @@ let meetApi: any; // JitsiMeetExternalAPI (async function() { try { - // The widget's options are encoded into the fragment to avoid leaking info to the server. The widget - // spec on the other hand requires the widgetId and parentUrl to show up in the regular query string. - const widgetQuery = qs.parse(window.location.hash.substring(1)); - const query = Object.assign({}, qs.parse(window.location.search.substring(1)), widgetQuery); + // The widget's options are encoded into the fragment to avoid leaking info to the server. + const widgetQuery = new URLSearchParams(window.location.hash.substring(1)); + // The widget spec on the other hand requires the widgetId and parentUrl to show up in the regular query string. + const realQuery = new URLSearchParams(window.location.search.substring(1)); const qsParam = (name: string, optional = false): string => { - if (!optional && (!query[name] || typeof (query[name]) !== 'string')) { + const vals = widgetQuery.has(name) ? widgetQuery.getAll(name) : realQuery.getAll(name); + if (!optional && vals.length !== 1) { throw new Error(`Expected singular ${name} in query string`); } - return query[name]; + return vals[0]; }; // If we have these params, expect a widget API to be available (ie. to be in an iframe diff --git a/src/vector/url_utils.ts b/src/vector/url_utils.ts index 1e14fb5c8..98c6e3936 100644 --- a/src/vector/url_utils.ts +++ b/src/vector/url_utils.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import * as qs from 'querystring'; +import { QueryDict, decodeParams } from "matrix-js-sdk/src/utils"; // We want to support some name / value pairs in the fragment // so we're re-using query string like format @@ -32,15 +32,15 @@ export function parseQsFromFragment(location: Location) { const result = { location: decodeURIComponent(hashparts[0]), - params: {}, + params: {}, }; if (hashparts.length > 1) { - result.params = qs.parse(hashparts[1]); + result.params = decodeParams(hashparts[1]); } return result; } -export function parseQs(location: Location) { - return qs.parse(location.search.substring(1)); +export function parseQs(location: Location): QueryDict { + return decodeParams(location.search.substring(1)); } diff --git a/test/unit-tests/url_utils-test.ts b/test/unit-tests/url_utils-test.ts new file mode 100644 index 000000000..784dde2d1 --- /dev/null +++ b/test/unit-tests/url_utils-test.ts @@ -0,0 +1,50 @@ +/* +Copyright 2020 New Vector Ltd + +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 { parseQsFromFragment, parseQs } from "../../src/vector/url_utils"; + +describe("url_utils.ts", function() { + // @ts-ignore + const location: Location = { + hash: "", + search: "", + }; + + it("parseQsFromFragment", function() { + location.hash = "/home?foo=bar"; + expect(parseQsFromFragment(location)).toEqual({ + location: "home", + params: { + "foo": "bar", + }, + }); + }); + + describe("parseQs", function() { + location.search = "?foo=bar"; + expect(parseQs(location)).toEqual({ + "foo": "bar", + }); + }); + + describe("parseQs with arrays", function() { + location.search = "?via=s1&via=s2&via=s2&foo=bar"; + expect(parseQs(location)).toEqual({ + "via": ["s1", "s2", "s2"], + "foo": "bar", + }); + }); +});