From 8fdb41412f3150eab352fe75ad1ff9e03194f15e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 Apr 2020 01:45:58 +0100 Subject: [PATCH 1/8] Use URLSearchParams instead of transitive dependency `querystring` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 3 +- src/vector/jitsi/index.ts | 6 +-- src/vector/url_utils.ts | 10 +++-- test/unit-tests/url_utils-test.ts | 42 ++++++++++++++++++ yarn.lock | 74 ++++++++++++++++++++++--------- 5 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 test/unit-tests/url_utils-test.ts diff --git a/package.json b/package.json index 45f99265c..d94cc1494 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "@babel/preset-typescript": "^7.7.4", "@babel/register": "^7.7.4", "@babel/runtime": "^7.7.6", + "@types/jest": "^25.2.1", "@types/modernizr": "^3.5.3", "@types/react": "16.9", "@types/react-dom": "^16.9.4", @@ -208,7 +209,7 @@ ], "testEnvironment": "jest-environment-jsdom-fourteen", "testMatch": [ - "/test/**/*-test.js" + "/test/**/*-test.*" ], "setupFilesAfterEnv": [ "/node_modules/matrix-react-sdk/test/setupTests.js" diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 50f07fb95..135f426d7 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -17,7 +17,7 @@ limitations under the License. // We have to trick webpack into loading our CSS for us. require("./index.scss"); -import * as qs from 'querystring'; +import { parseQs, parseQsFromFragment } from "../url_utils"; import { Capability, WidgetApi } from "matrix-react-sdk/src/widgets/WidgetApi"; // Dev note: we use raw JS without many dependencies to reduce bundle size. @@ -40,8 +40,8 @@ let widgetApi: WidgetApi; 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); + const widgetQuery = parseQsFromFragment(window.location); + const query = Object.assign({}, parseQs(window.location), widgetQuery.params); const qsParam = (name: string, optional = false): string => { if (!optional && (!query[name] || typeof (query[name]) !== 'string')) { throw new Error(`Expected singular ${name} in query string`); diff --git a/src/vector/url_utils.ts b/src/vector/url_utils.ts index 1e14fb5c8..b8b0da326 100644 --- a/src/vector/url_utils.ts +++ b/src/vector/url_utils.ts @@ -14,7 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import * as qs from 'querystring'; +function searchParamsToObject(params: URLSearchParams) { + return Object.fromEntries([...params.entries()]); +} // We want to support some name / value pairs in the fragment // so we're re-using query string like format @@ -32,15 +34,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 = searchParamsToObject(new URLSearchParams(hashparts[1])); } return result; } export function parseQs(location: Location) { - return qs.parse(location.search.substring(1)); + return searchParamsToObject(new URLSearchParams(location.search)); } diff --git a/test/unit-tests/url_utils-test.ts b/test/unit-tests/url_utils-test.ts new file mode 100644 index 000000000..1d5a4d29f --- /dev/null +++ b/test/unit-tests/url_utils-test.ts @@ -0,0 +1,42 @@ +/* +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", + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 8a9bc0e57..21a41d296 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1160,6 +1160,16 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" +"@jest/types@^25.3.0": + version "25.3.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.3.0.tgz#88f94b277a1d028fd7117bc1f74451e0fc2131e7" + integrity sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^3.0.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1269,6 +1279,14 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/jest@^25.2.1": + version "25.2.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" + integrity sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA== + dependencies: + jest-diff "^25.2.1" + pretty-format "^25.2.1" + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" @@ -1357,7 +1375,7 @@ dependencies: "@types/yargs-parser" "*" -"@types/yargs@^15.0.4": +"@types/yargs@^15.0.0", "@types/yargs@^15.0.4": version "15.0.4" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== @@ -3838,6 +3856,11 @@ diff-sequences@^24.9.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== +diff-sequences@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" + integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -6654,6 +6677,16 @@ jest-diff@^24.9.0: jest-get-type "^24.9.0" pretty-format "^24.9.0" +jest-diff@^25.2.1: + version "25.3.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" + integrity sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w== + dependencies: + chalk "^3.0.0" + diff-sequences "^25.2.6" + jest-get-type "^25.2.6" + pretty-format "^25.3.0" + jest-docblock@^24.3.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" @@ -6712,6 +6745,11 @@ jest-get-type@^24.9.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== +jest-get-type@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" + integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== + jest-haste-map@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" @@ -7645,8 +7683,8 @@ matrix-mock-request@^1.2.3: create-react-class "^15.6.0" diff-dom "^4.1.3" diff-match-patch "^1.0.4" - emojibase-data "^5.0.1" - emojibase-regex "^4.0.1" + emojibase-data "^4.0.2" + emojibase-regex "^3.0.0" escape-html "^1.0.3" file-saver "^1.3.3" filesize "3.5.6" @@ -8191,22 +8229,6 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-pre-gyp@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" @@ -9760,6 +9782,16 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" +pretty-format@^25.2.1, pretty-format@^25.3.0: + version "25.3.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.3.0.tgz#d0a4f988ff4a6cd350342fdabbb809aeb4d49ad5" + integrity sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA== + dependencies: + "@jest/types" "^25.3.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -10088,7 +10120,7 @@ react-focus-lock@^2.2.1: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -11693,7 +11725,7 @@ tar-stream@^2.1.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4, tar@^4.4.2: +tar@^4: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== From c044e1a00c0f55ae268d8e3092ec41f3debb7082 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 Apr 2020 01:54:48 +0100 Subject: [PATCH 2/8] fix typescript Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/url_utils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vector/url_utils.ts b/src/vector/url_utils.ts index b8b0da326..6ebabfc4d 100644 --- a/src/vector/url_utils.ts +++ b/src/vector/url_utils.ts @@ -14,8 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ +interface IParamsObject { + [key: string]: string; +} + function searchParamsToObject(params: URLSearchParams) { - return Object.fromEntries([...params.entries()]); + return Object.fromEntries([...params.entries()]); } // We want to support some name / value pairs in the fragment @@ -34,7 +38,7 @@ export function parseQsFromFragment(location: Location) { const result = { location: decodeURIComponent(hashparts[0]), - params: {}, + params: {}, }; if (hashparts.length > 1) { From 6764c7e77904377aff3315c88b74ba73d3536082 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Apr 2020 21:23:40 +0100 Subject: [PATCH 3/8] move urlSearchParamsToObject and global.d.ts to react-sdk Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 1 - src/@types/global.d.ts | 12 +----------- src/vector/url_utils.ts | 10 ++++------ 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index d94cc1494..de533bc54 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,6 @@ "@babel/register": "^7.7.4", "@babel/runtime": "^7.7.6", "@types/jest": "^25.2.1", - "@types/modernizr": "^3.5.3", "@types/react": "16.9", "@types/react-dom": "^16.9.4", "autoprefixer": "^9.7.3", diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 6a5adec6d..2e2f35f60 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -14,25 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import "modernizr"; +import "matrix-react-sdk/src/@types/global"; import {Renderer} from "react-dom"; declare global { interface Window { - Modernizr: ModernizrAPI & FeatureDetects; - Olm: { - init: () => Promise; - }; - mxSendRageshake: (text: string, withLogs?: boolean) => void; matrixChat: ReturnType; // electron-only ipcRenderer: any; } - - // workaround for https://github.com/microsoft/TypeScript/issues/30933 - interface ObjectConstructor { - fromEntries?(xs: [string|number|symbol, any][]): object - } } diff --git a/src/vector/url_utils.ts b/src/vector/url_utils.ts index 6ebabfc4d..d5efcdaab 100644 --- a/src/vector/url_utils.ts +++ b/src/vector/url_utils.ts @@ -14,14 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {urlSearchParamsToObject} from "matrix-react-sdk/src/utils/UrlUtils"; + interface IParamsObject { [key: string]: string; } -function searchParamsToObject(params: URLSearchParams) { - return Object.fromEntries([...params.entries()]); -} - // We want to support some name / value pairs in the fragment // so we're re-using query string like format // @@ -42,11 +40,11 @@ export function parseQsFromFragment(location: Location) { }; if (hashparts.length > 1) { - result.params = searchParamsToObject(new URLSearchParams(hashparts[1])); + result.params = urlSearchParamsToObject(new URLSearchParams(hashparts[1])); } return result; } export function parseQs(location: Location) { - return searchParamsToObject(new URLSearchParams(location.search)); + return urlSearchParamsToObject(new URLSearchParams(location.search)); } From d914b13c1b739e43cc1a8c066442de3dd932a504 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Apr 2020 21:28:23 +0100 Subject: [PATCH 4/8] remove dependency on `qs` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- yarn.lock | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index 21a41d296..62bd1a9c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1297,11 +1297,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/modernizr@^3.5.3": - version "3.5.3" - resolved "https://registry.yarnpkg.com/@types/modernizr/-/modernizr-3.5.3.tgz#8ef99e6252191c1d88647809109dc29884ba6d7a" - integrity sha512-jhMOZSS0UGYTS9pqvt6q3wtT3uvOSve5piTEmTMx3zzTuBLvSIMxSIBIc3d5lajVD5h4xc41AMZD2M5orN3PxA== - "@types/node@*": version "13.11.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" @@ -4183,15 +4178,15 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojibase-data@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-5.0.1.tgz#ce6fe36b4affd3578e0be8779211018a2fdae960" - integrity sha512-rYWlogJ2q5P78U8Xx1vhsXHcYKu1wFnr7+o6z9QHssZ1SsJLTCkJINZIPHRFWuDreAUK457TkqHpdOXElu0fzA== +emojibase-data@^4.0.2: + version "4.2.1" + resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-4.2.1.tgz#3d1f0c69ddbb2ca7b7014f5e34654190802a40df" + integrity sha512-O0vxoPMgVkRq/uII/gdAjz9RwNv6ClJrd3J9QCCRC4btZRmeut/qohC/Fi+NNXUcjY08RWNTvxSnq/vij8hvrw== -emojibase-regex@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/emojibase-regex/-/emojibase-regex-4.0.1.tgz#a2cd4bbb42825422da9ec72f15e970bc2c90b46a" - integrity sha512-S42UHkFfz15i4NNz+wi9iMKFo+B6Kalc6PJLpYX0BUANViXw4vSyYZMFdBGRLduSabWHuEcTLZl9xOa2YP3eJw== +emojibase-regex@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/emojibase-regex/-/emojibase-regex-3.2.1.tgz#122935958c9a49c96bb29ac69ccbbac0b2e7022d" + integrity sha512-VAX2Rc2U/alu5q6P2cET2alzC63o1Uarm6Ea/b3ab+KOzxZT4JKmB0tCU1sTZvfNKa16KMLCK2k7hJBHJq4vWQ== emojis-list@^2.0.0: version "2.1.0" From 078d6a0d98d2890828c984addce4f3fc7e2b1124 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Apr 2020 21:36:49 +0100 Subject: [PATCH 5/8] remove dependency on `url` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 3 +-- src/vector/app.js | 9 +++------ src/vector/platform/WebPlatform.js | 7 +++---- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index de533bc54..0b83a69f9 100644 --- a/package.json +++ b/package.json @@ -76,8 +76,7 @@ "react": "^16.9.0", "react-dom": "^16.9.0", "sanitize-html": "^1.19.1", - "ua-parser-js": "^0.7.19", - "url": "^0.11.0" + "ua-parser-js": "^0.7.19" }, "devDependencies": { "@babel/cli": "^7.7.5", diff --git a/src/vector/app.js b/src/vector/app.js index 930576e2d..e087d8c2f 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -31,8 +31,6 @@ import AutoDiscoveryUtils from 'matrix-react-sdk/src/utils/AutoDiscoveryUtils'; import {AutoDiscovery} from "matrix-js-sdk/src/autodiscovery"; import * as Lifecycle from "matrix-react-sdk/src/Lifecycle"; -import url from 'url'; - import {parseQs, parseQsFromFragment} from './url_utils'; import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg'; @@ -118,11 +116,10 @@ function onTokenLoginCompleted() { // if we did a token login, we're now left with the token, hs and is // url as query params in the url; a little nasty but let's redirect to // clear them. - const parsedUrl = url.parse(window.location.href); + const parsedUrl = new URL(window.location); parsedUrl.search = ""; - const formatted = url.format(parsedUrl); - console.log("Redirecting to " + formatted + " to drop loginToken " + - "from queryparams"); + const formatted = parsedUrl.toString(); + console.log("Redirecting to " + formatted + " to drop loginToken from queryparams"); window.location.href = formatted; } diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js index 8db12856f..4524d720c 100644 --- a/src/vector/platform/WebPlatform.js +++ b/src/vector/platform/WebPlatform.js @@ -22,7 +22,6 @@ import request from 'browser-request'; import dis from 'matrix-react-sdk/src/dispatcher.js'; import { _t } from 'matrix-react-sdk/src/languageHandler'; -import url from 'url'; import UAParser from 'ua-parser-js'; const POKE_RATE_MS = 10 * 60 * 1000; // 10 min @@ -179,15 +178,15 @@ export default class WebPlatform extends VectorBasePlatform { getDefaultDeviceDisplayName(): string { // strip query-string and fragment from uri - const u = url.parse(window.location.href); + const u = new URL(window.location); u.search = ""; u.hash = ""; - const appName = u.format(); + const appName = u.toString(); const ua = new UAParser(); const browserName = ua.getBrowser().name || "unknown browser"; const osName = ua.getOS().name || "unknown os"; - return _t('%(appName)s via %(browserName)s on %(osName)s', {appName: appName, browserName: browserName, osName: osName}); + return _t('%(appName)s via %(browserName)s on %(osName)s', {appName, browserName, osName}); } screenCaptureErrorString(): ?string { From 75e4d164626c9241bae6f9504b06a7225dc16336 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 16 Jul 2021 13:10:58 +0100 Subject: [PATCH 6/8] use js-sdk decodeParams utility --- src/vector/url_utils.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/vector/url_utils.ts b/src/vector/url_utils.ts index d5efcdaab..98c6e3936 100644 --- a/src/vector/url_utils.ts +++ b/src/vector/url_utils.ts @@ -14,11 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {urlSearchParamsToObject} from "matrix-react-sdk/src/utils/UrlUtils"; - -interface IParamsObject { - [key: string]: string; -} +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 @@ -36,15 +32,15 @@ export function parseQsFromFragment(location: Location) { const result = { location: decodeURIComponent(hashparts[0]), - params: {}, + params: {}, }; if (hashparts.length > 1) { - result.params = urlSearchParamsToObject(new URLSearchParams(hashparts[1])); + result.params = decodeParams(hashparts[1]); } return result; } -export function parseQs(location: Location) { - return urlSearchParamsToObject(new URLSearchParams(location.search)); +export function parseQs(location: Location): QueryDict { + return decodeParams(location.search.substring(1)); } From 26fef6f294194b2cc7d52d565d03c1549cddfb78 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 16 Jul 2021 13:45:10 +0100 Subject: [PATCH 7/8] actually run the new test and remove unrelated tweak --- package.json | 2 +- src/@types/global.d.ts | 5 ----- test/unit-tests/url_utils-test.ts | 10 +++++++++- 3 files changed, 10 insertions(+), 7 deletions(-) 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/@types/global.d.ts b/src/@types/global.d.ts index 805639310..521150648 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -35,11 +35,6 @@ type ElectronChannel = declare global { interface Window { - Modernizr: ModernizrAPI & FeatureDetects; - Olm: { - init: () => Promise; - }; - mxSendRageshake: (text: string, withLogs?: boolean) => void; matrixChat: ReturnType; diff --git a/test/unit-tests/url_utils-test.ts b/test/unit-tests/url_utils-test.ts index 1d5a4d29f..784dde2d1 100644 --- a/test/unit-tests/url_utils-test.ts +++ b/test/unit-tests/url_utils-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {parseQsFromFragment, parseQs} from "../../src/vector/url_utils"; +import { parseQsFromFragment, parseQs } from "../../src/vector/url_utils"; describe("url_utils.ts", function() { // @ts-ignore @@ -39,4 +39,12 @@ describe("url_utils.ts", function() { "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", + }); + }); }); From c7a935777d441d2f8d1de20dfe0f33bf73b73c1f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 16 Jul 2021 19:37:48 +0100 Subject: [PATCH 8/8] Fix the jitsi qs parsing, as the `?` after `#` here is optional, unlike in EW --- src/vector/jitsi/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 7d7b05de1..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 { parseQs, parseQsFromFragment } from "../url_utils"; 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 = parseQsFromFragment(window.location); - const query = Object.assign({}, parseQs(window.location), widgetQuery.params); + // 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