2023-04-01 03:32:34 -05:00
|
|
|
var invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im;
|
|
|
|
var htmlEntitiesRegex = /&#(\w+)(^\w|;)?/g;
|
|
|
|
var htmlCtrlEntityRegex = /&(newline|tab);/gi;
|
|
|
|
var ctrlCharactersRegex = /[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim;
|
|
|
|
var urlSchemeRegex = /^.+(:|:)/gim;
|
|
|
|
var relativeFirstCharacters = [".", "/"];
|
|
|
|
function isRelativeUrlWithoutProtocol(url) {
|
2020-05-29 10:26:47 -05:00
|
|
|
return relativeFirstCharacters.indexOf(url[0]) > -1;
|
2023-04-01 03:32:34 -05:00
|
|
|
}
|
|
|
|
// adapted from https://stackoverflow.com/a/29824550/2601552
|
|
|
|
function decodeHtmlCharacters(str) {
|
|
|
|
return str.replace(htmlEntitiesRegex, function (match, dec) {
|
|
|
|
return String.fromCharCode(dec);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function sanitizeUrl(url) {
|
|
|
|
var sanitizedUrl = decodeHtmlCharacters(url || "")
|
|
|
|
.replace(htmlCtrlEntityRegex, "")
|
|
|
|
.replace(ctrlCharactersRegex, "")
|
|
|
|
.trim();
|
|
|
|
if (!sanitizedUrl) {
|
|
|
|
return "about:blank";
|
2020-05-29 10:26:47 -05:00
|
|
|
}
|
|
|
|
if (isRelativeUrlWithoutProtocol(sanitizedUrl)) {
|
2023-04-01 03:32:34 -05:00
|
|
|
return sanitizedUrl;
|
2020-05-29 10:26:47 -05:00
|
|
|
}
|
2023-04-01 03:32:34 -05:00
|
|
|
var urlSchemeParseResults = sanitizedUrl.match(urlSchemeRegex);
|
2020-05-29 10:26:47 -05:00
|
|
|
if (!urlSchemeParseResults) {
|
2023-04-01 03:32:34 -05:00
|
|
|
return sanitizedUrl;
|
2020-05-29 10:26:47 -05:00
|
|
|
}
|
2023-04-01 03:32:34 -05:00
|
|
|
var urlScheme = urlSchemeParseResults[0];
|
|
|
|
if (invalidProtocolRegex.test(urlScheme)) {
|
|
|
|
return "about:blank";
|
2020-05-29 10:26:47 -05:00
|
|
|
}
|
2020-02-19 13:08:17 -06:00
|
|
|
return sanitizedUrl;
|
2023-04-01 03:32:34 -05:00
|
|
|
}
|
2023-04-01 03:47:56 -05:00
|
|
|
|
|
|
|
window.sanitizeUrl = sanitizeUrl;
|