diff --git a/__test__/support/helpers/api.ts b/__test__/support/helpers/api.ts index 6699418c0..815e245a8 100644 --- a/__test__/support/helpers/api.ts +++ b/__test__/support/helpers/api.ts @@ -9,18 +9,14 @@ export function isAsyncFunction(fn: () => any): boolean { ); } -export const getFunctionSignature = (func: () => any) => { - // Convert the function to a string - const funcStr = func.toString(); - - // Use a regular expression to match the function signature - const signatureRegex = - /^(async\s*)?(public\s*)?(protected\s*)?(private\s*)?(static\s*)?(function)?(\s*\w*\s*\(([^)]*(?:\s*:\s*[^,]+,?)*)\))/; - const match = funcStr.match(signatureRegex); - - // Return the matched signature, or null if not found - return match ? match[0] : null; -}; +const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; +const ARGUMENT_NAMES = /([^\s,]+)/g; +function getParamNames(func: () => unknown): null | string[] { + const fnStr = func.toString().replace(STRIP_COMMENTS, ''); + return fnStr + .slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')) + .match(ARGUMENT_NAMES); +} export const matchNestedProperties = ( api: any, @@ -83,11 +79,9 @@ export const matchNestedFunctions = ( expect(typeof parentObject[namespaceName][name]).toBe('function'); expect(parentObject[namespaceName][name].length).toBe(args.length); - // for each argument, check the name and type + const expectedArgs = getParamNames(parentObject[namespaceName][name]); for (let i = 0; i < args.length; i++) { - const arg = args[i]; - const funcSig = getFunctionSignature(parentObject[namespaceName][name]); - expect(funcSig).toContain(arg.name); + expect(expectedArgs?.[i]).toContain(args[i].name); // to do: check the type } diff --git a/__test__/support/utils/Random.ts b/__test__/support/utils/Random.ts index befb491ec..a1bf38df7 100644 --- a/__test__/support/utils/Random.ts +++ b/__test__/support/utils/Random.ts @@ -35,32 +35,4 @@ export default class Random { ), ); } - - public static getRandomUuid(): string { - let uuidStr = ''; - const crypto = - typeof window === 'undefined' - ? (global as any).crypto - : window.crypto || (window).msCrypto; - if (crypto) { - uuidStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( - /[xy]/g, - function (c) { - const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }, - ); - } else { - uuidStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( - /[xy]/g, - function (c) { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }, - ); - } - return uuidStr; - } } diff --git a/__test__/unit/helpers/configHelper.test.ts b/__test__/unit/helpers/configHelper.test.ts index 6204415db..41bfb469c 100644 --- a/__test__/unit/helpers/configHelper.test.ts +++ b/__test__/unit/helpers/configHelper.test.ts @@ -2,7 +2,7 @@ import { AppUserConfig, ConfigIntegrationKind, } from '../../../src/shared/models/AppConfig'; -import Random from '../../support/utils/Random'; +import { getRandomUuid } from '../../../src/shared/utils/utils'; import { TestEnvironment } from '../../support/environment/TestEnvironment'; import { HttpHttpsEnvironment } from '../../support/models/HttpHttpsEnvironment'; import { getFinalAppConfig } from '../../support/helpers/configHelper'; @@ -24,7 +24,7 @@ describe('ConfigHelper Tests', () => { test('promptOptions 1 - autoRegister = true backwards compatibility for custom integration shows native on HTTPS', async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -46,7 +46,7 @@ describe('ConfigHelper Tests', () => { ); const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -62,7 +62,7 @@ describe('ConfigHelper Tests', () => { test('promptOptions 3 - autoRegister = false backwards compatibility for custom integration (no enabled prompts)', async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: false, }; @@ -78,7 +78,7 @@ describe('ConfigHelper Tests', () => { test(`promptOptions 4 - autoRegister = true backwards compatibility for custom integration (ignores config, shows native on HTTPS)`, async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; (fakeUserConfig as any).promptOptions = { @@ -105,7 +105,7 @@ describe('ConfigHelper Tests', () => { ); const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -129,7 +129,7 @@ describe('ConfigHelper Tests', () => { test(`promptOptions 6 - autoRegister = true backwards compatibility for custom integration (ignores config, shows native on HTTPS)`, async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -158,7 +158,7 @@ describe('ConfigHelper Tests', () => { ); const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -183,7 +183,7 @@ describe('ConfigHelper Tests', () => { test(`promptOptions 8 - autoRegister = true backwards compatibility for custom integration (ignores config, shows native on HTTPS)`, async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -210,7 +210,7 @@ describe('ConfigHelper Tests', () => { test(`promptOptions 9 - autoRegister = true backwards compatibility for custom integration (ignores config, shows native on HTTPS)`, async () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -243,7 +243,7 @@ describe('ConfigHelper Tests', () => { ); const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -270,7 +270,7 @@ describe('ConfigHelper Tests', () => { test('autoResubscribe - autoRegister backwards compatibility for custom integration 1', () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: true, }; @@ -287,7 +287,7 @@ describe('ConfigHelper Tests', () => { test('autoResubscribe - autoRegister backwards compatibility for custom integration 2', () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), }; const fakeServerConfig = TestContext.getFakeServerAppConfig( @@ -305,7 +305,7 @@ describe('ConfigHelper Tests', () => { test('autoResubscribe - autoRegister backwards compatibility for custom integration 3', () => { const fakeUserConfig: AppUserConfig = { - appId: Random.getRandomUuid(), + appId: getRandomUuid(), autoRegister: false, autoResubscribe: true, }; diff --git a/express_webpack/amp/index.html b/express_webpack/amp/index.html index dbadd4072..c819ebaee 100644 --- a/express_webpack/amp/index.html +++ b/express_webpack/amp/index.html @@ -6,16 +6,8 @@ const SERVICE_WORKER_PATH = "push/onesignal/"; function getUrlQueryParam(name) { - var url = window.location.href; - // This is just to avoid case sensitiveness - url = url.toLowerCase(); - // This is just to avoid case sensitiveness for query parameter name - name = name.replace(/[\[\]]/g, "\\$&").toLowerCase(); - var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, " ")); + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(name); } const appId = getUrlQueryParam('app_id'); diff --git a/express_webpack/index.html b/express_webpack/index.html index 415bbfcaa..a85e97b58 100644 --- a/express_webpack/index.html +++ b/express_webpack/index.html @@ -17,16 +17,8 @@ let showEventAlertToggleSetting = false; function getUrlQueryParam(name) { - var url = window.location.href; - // This is just to avoid case sensitiveness - url = url.toLowerCase(); - // This is just to avoid case sensitiveness for query parameter name - name = name.replace(/[\[\]]/g, "\\$&").toLowerCase(); - var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, " ")); + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(name); } const appId = getUrlQueryParam('app_id'); diff --git a/express_webpack/package.json b/express_webpack/package.json index 711204cd6..c0c045b64 100644 --- a/express_webpack/package.json +++ b/express_webpack/package.json @@ -13,9 +13,11 @@ "license": "ISC", "dependencies": { "express": "^4.17.3", + "express-rate-limit": "^7.1.2", "fs": "0.0.1-security", "https": "^1.0.0", - "nodemon": "^1.19.3" + "nodemon": "^1.19.3", + "sanitize-filename": "^1.6.3" }, "devDependencies": { "@babel/core": "^7.6.2", diff --git a/express_webpack/server.js b/express_webpack/server.js index 2f062318b..41c4c4fad 100644 --- a/express_webpack/server.js +++ b/express_webpack/server.js @@ -2,26 +2,36 @@ const path = require('path'); const express = require('express'); const https = require('https'); const fs = require('fs'); +var sanitize = require("sanitize-filename"); + const app = express(), DIST_DIR = __dirname, HTML_FILE = path.join(DIST_DIR, 'index.html'), SDK_FILES = path.join(DIST_DIR, '../build/releases/'); + +var RateLimit = require('express-rate-limit'); +var limiter = RateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // max 100 requests per windowMs +}); +// apply rate limiter to all requests +app.use(limiter); + const options = { key: fs.readFileSync('certs/dev-ssl.key'), cert: fs.readFileSync('certs/dev-ssl.crt') } -app.use(express.static(DIST_DIR)) app.get('/', (req, res) => { res.sendFile(HTML_FILE); }) app.get('/sdks/web/v16/:file', (req, res) => { - res.sendFile(SDK_FILES + req.params.file); + res.sendFile(SDK_FILES + sanitize(req.params.file)); }); app.get('/:file', (req, res) => { - res.sendFile(req.params.file); + res.sendFile(sanitize(req.params.file), { root: __dirname }); }); https.createServer(options, app).listen(4001, () => console.log("express_webpack: listening on port 4001 (https)")); diff --git a/express_webpack/yarn.lock b/express_webpack/yarn.lock index 0734125f4..000152252 100644 --- a/express_webpack/yarn.lock +++ b/express_webpack/yarn.lock @@ -2148,6 +2148,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +express-rate-limit@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.1.2.tgz#42156c9135ca7b77d4e0d74b06162bfe02cd45f7" + integrity sha512-uvkFt5JooXDhUhrfgqXLyIsAMRCtU1o8W/p0Q2p5U2ude7fEOfFaP0kSYbHOHmPbA9ZEm1JqrRne3vL9pVCBXA== + express@^4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" @@ -4101,6 +4106,13 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +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" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -4544,6 +4556,13 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" +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" + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -4710,6 +4729,11 @@ 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.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" diff --git a/src/core/requestService/RequestService.ts b/src/core/requestService/RequestService.ts index ddebab910..c4ce0d972 100644 --- a/src/core/requestService/RequestService.ts +++ b/src/core/requestService/RequestService.ts @@ -9,6 +9,12 @@ import AliasPair from './AliasPair'; import { UpdateUserPayload } from './UpdateUserPayload'; import UserData from '../models/UserData'; import { RequestMetadata } from '../models/RequestMetadata'; +import { encodeRFC3986URIComponent } from '../../shared/utils/Encoding'; +import OneSignalUtils from '../../shared/utils/OneSignalUtils'; +import { + SdkInitError, + SdkInitErrorKind, +} from '../../shared/errors/SdkInitError'; export class RequestService { /* U S E R O P E R A T I O N S */ @@ -61,6 +67,10 @@ export class RequestService { payload: UpdateUserPayload, ): Promise { const { appId, subscriptionId } = requestMetadata; + if (!OneSignalUtils.isValidUuid(appId)) { + throw new SdkInitError(SdkInitErrorKind.InvalidAppId); + } + const subscriptionHeader = subscriptionId ? { 'OneSignal-Subscription-Id': subscriptionId } : undefined; @@ -75,8 +85,13 @@ export class RequestService { headers = { ...headers, ...requestMetadata.jwtHeader }; } + const sanitizedAlias = { + label: encodeRFC3986URIComponent(alias.label), + id: encodeRFC3986URIComponent(alias.id), + }; + return OneSignalApiBase.patch( - `apps/${appId}/users/by/${alias.label}/${alias.id}`, + `apps/${appId}/users/by/${sanitizedAlias.label}/${sanitizedAlias.id}`, payload, headers, ); diff --git a/src/page/bell/AnimatedElement.ts b/src/page/bell/AnimatedElement.ts index f31bd450f..e46f8aede 100755 --- a/src/page/bell/AnimatedElement.ts +++ b/src/page/bell/AnimatedElement.ts @@ -208,10 +208,10 @@ export default class AnimatedElement { this.nestedContentSelector, ); if (nestedContent) { - nestedContent.innerHTML = value; + nestedContent.textContent = value; } } else { - this.element.innerHTML = value; + this.element.textContent = value; } } diff --git a/src/page/bell/Bell.ts b/src/page/bell/Bell.ts index be35c108a..d7934f73d 100755 --- a/src/page/bell/Bell.ts +++ b/src/page/bell/Bell.ts @@ -5,7 +5,6 @@ import { addCssClass, addDomElement, contains, - decodeHtmlEntities, delay, nothing, once, @@ -30,6 +29,7 @@ import { import SubscriptionChangeEvent from '../models/SubscriptionChangeEvent'; import { bowserCastle } from '../../shared/utils/bowserCastle'; import OneSignal from '../../onesignal/OneSignal'; +import BrowserUtils from '../../shared/utils/BrowserUtils'; const logoSvg = ``; @@ -277,7 +277,7 @@ export default class Bell { resolve(); }); } else { - this.message.content = decodeHtmlEntities( + this.message.content = BrowserUtils.decodeHtmlEntities( this.message.getTipForState(), ); this.message.contentType = Message.TYPES.TIP; diff --git a/src/page/bell/Message.ts b/src/page/bell/Message.ts index 600f4a862..249634c09 100755 --- a/src/page/bell/Message.ts +++ b/src/page/bell/Message.ts @@ -1,10 +1,6 @@ +import BrowserUtils from '../../shared/utils/BrowserUtils'; import Log from '../../shared/libraries/Log'; -import { - decodeHtmlEntities, - delay, - getConsoleStyle, - nothing, -} from '../../shared/utils/utils'; +import { delay, getConsoleStyle, nothing } from '../../shared/utils/utils'; import AnimatedElement from './AnimatedElement'; import Bell from './Bell'; @@ -47,7 +43,7 @@ export default class Message extends AnimatedElement { ); return (this.shown ? this.hide() : nothing()) .then(() => { - this.content = decodeHtmlEntities(content); + this.content = BrowserUtils.decodeHtmlEntities(content); this.contentType = type; }) .then(() => { @@ -75,7 +71,7 @@ export default class Message extends AnimatedElement { } enqueue(message: string) { - this.queued.push(decodeHtmlEntities(message)); + this.queued.push(BrowserUtils.decodeHtmlEntities(message)); return new Promise((resolve) => { if (this.bell.badge.shown) { this.bell.badge diff --git a/src/shared/services/Postmam.ts b/src/shared/services/Postmam.ts index 2f2f216d9..b25e6251c 100755 --- a/src/shared/services/Postmam.ts +++ b/src/shared/services/Postmam.ts @@ -286,7 +286,9 @@ export default class Postmam { if (typeof onReply === 'function') { this.replies[messageBundle.id] = onReply; } - this.windowReference.postMessage(messageBundle, '*'); + + // This is a dead code path, this file will be deleted in the future. + // this.windowReference.postMessage(messageBundle, '*'); } /** diff --git a/src/shared/utils/BrowserUtils.ts b/src/shared/utils/BrowserUtils.ts index 21122536f..1616cd57d 100644 --- a/src/shared/utils/BrowserUtils.ts +++ b/src/shared/utils/BrowserUtils.ts @@ -1,20 +1,12 @@ -import Environment from '../helpers/Environment'; - export class BrowserUtils { - private static decodeTextArea: HTMLTextAreaElement | null = null; - public static decodeHtmlEntities(text: string) { - if (Environment.isBrowser()) { - if (!BrowserUtils.decodeTextArea) { - BrowserUtils.decodeTextArea = document.createElement('textarea'); - } - } - if (BrowserUtils.decodeTextArea) { - BrowserUtils.decodeTextArea.innerHTML = text; - return BrowserUtils.decodeTextArea.value; - } else { - // Not running in a browser environment, text cannot be decoded + // Decodes HTML encoded characters (like &) into their displayed value. + // Example: "<b>test</b>" becomes "test" + public static decodeHtmlEntities(text: string): string { + if (typeof DOMParser === 'undefined') { return text; } + const doc = new DOMParser().parseFromString(text, 'text/html'); + return doc.documentElement.textContent || ''; } } diff --git a/src/shared/utils/Encoding.ts b/src/shared/utils/Encoding.ts index 92d1611c6..7f30d7239 100644 --- a/src/shared/utils/Encoding.ts +++ b/src/shared/utils/Encoding.ts @@ -98,3 +98,11 @@ export function base64Decode(str) { .join(''), ); } + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986 +export function encodeRFC3986URIComponent(str: string): string { + return encodeURIComponent(str).replace( + /[!'()*]/g, + (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`, + ); +} diff --git a/src/shared/utils/OneSignalUtils.ts b/src/shared/utils/OneSignalUtils.ts index ecd2473e9..eff0a0266 100644 --- a/src/shared/utils/OneSignalUtils.ts +++ b/src/shared/utils/OneSignalUtils.ts @@ -99,30 +99,18 @@ export class OneSignalUtils { } public static getRandomUuid(): string { - let uuidStr = ''; const crypto = typeof window === 'undefined' ? (global as any).crypto : window.crypto || (window).msCrypto; - if (crypto) { - uuidStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( - /[xy]/g, - function (c) { - const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }, - ); - } else { - uuidStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( - /[xy]/g, - function (c) { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }, - ); - } + const uuidStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( + /[xy]/g, + function (c) { + const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }, + ); return uuidStr; } diff --git a/src/shared/utils/utils.ts b/src/shared/utils/utils.ts index db8c240c1..832d973a1 100755 --- a/src/shared/utils/utils.ts +++ b/src/shared/utils/utils.ts @@ -3,9 +3,7 @@ import { WindowEnvironmentKind } from '../models/WindowEnvironmentKind'; import Database from '../services/Database'; import { OneSignalUtils } from './OneSignalUtils'; import { PermissionUtils } from './PermissionUtils'; -import { BrowserUtils } from './BrowserUtils'; import { Utils } from '../context/Utils'; -import bowser from 'bowser'; import TimeoutError from '../errors/TimeoutError'; import Log from '../libraries/Log'; import { bowserCastle } from './bowserCastle'; @@ -14,10 +12,6 @@ export function isArray(variable: any) { return Object.prototype.toString.call(variable) === '[object Array]'; } -export function decodeHtmlEntities(text: string) { - return BrowserUtils.decodeHtmlEntities(text); -} - export function removeDomElement(selector: string) { const els = document.querySelectorAll(selector); if (els.length > 0) { @@ -95,7 +89,7 @@ export function isValidEmail(email: string | undefined | null) { !!email && !!email.match( // eslint-disable-next-line no-control-regex - /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/, + /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/, ) ); } @@ -273,17 +267,6 @@ export function isValidUuid(uuid: string) { return OneSignalUtils.isValidUuid(uuid); } -export function getUrlQueryParam(name: string) { - let url = window.location.href; - url = url.toLowerCase(); // This is just to avoid case sensitiveness - name = name.replace(/[[\]]/g, '\\$&').toLowerCase(); // This is just to avoid case sensitiveness for query parameter name - const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); -} - /** * Wipe OneSignal-related IndexedDB data on the "correct" computed origin, but OneSignal must be initialized first to use. */