url-sanitizer 0.7.4 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/url-sanitizer.js +90 -96
- package/dist/url-sanitizer.js.map +2 -2
- package/dist/url-sanitizer.min.js +3 -3
- package/dist/url-sanitizer.min.js.map +3 -3
- package/package.json +3 -3
- package/src/mjs/uri-util.js +101 -127
package/README.md
CHANGED
|
@@ -36,6 +36,8 @@ import urlSanitizer, {
|
|
|
36
36
|
|
|
37
37
|
Sanitize the given URL.
|
|
38
38
|
* `data` and `file` schemes must be explicitly allowed.
|
|
39
|
+
* `blob` URLs are not currently allowed and will return `null`.
|
|
40
|
+
See [Figure out how to sanitize the blob URL · Issue #4](https://github.com/asamuzaK/urlSanitizer/issues/4)
|
|
39
41
|
|
|
40
42
|
### Parameters
|
|
41
43
|
|
|
@@ -61,7 +63,7 @@ console.log(decodeURIComponent(res1));
|
|
|
61
63
|
const res2 = await sanitizeURL('data:text/html,<div><script>alert(1);</script></div><p onclick="alert(2)"></p>', {
|
|
62
64
|
allow: ['data']
|
|
63
65
|
})
|
|
64
|
-
//
|
|
66
|
+
// => 'data:text/html,%3Cdiv%3E%3C/div%3E%3Cp%3E%3C/p%3E'
|
|
65
67
|
|
|
66
68
|
console.log(decodeURIComponent(res2));
|
|
67
69
|
// => 'data:text/html,<div></div><p></p>'
|
|
@@ -71,14 +73,14 @@ const base64data3 = btoa('<div><script>alert(1);</script></div>');
|
|
|
71
73
|
const res3 = await sanitizeURL(`data:text/html;base64,${base64data3}`, {
|
|
72
74
|
allow: ['data']
|
|
73
75
|
})
|
|
74
|
-
// => 'data:text/html,%3Cdiv%3E%3C%
|
|
76
|
+
// => 'data:text/html,%3Cdiv%3E%3C/div%3E'
|
|
75
77
|
|
|
76
78
|
console.log(decodeURIComponent(res3));
|
|
77
79
|
// => 'data:text/html,<div></div>'
|
|
78
80
|
|
|
79
81
|
const base64data4 = btoa('<div><img src="javascript:alert(1)"></div>');
|
|
80
82
|
const res4 = await sanitizeURL(`data:text/html;base64,${base64data4}`);
|
|
81
|
-
// => 'data:text/html,%3Cdiv%3E%3Cimg%3E%3C%
|
|
83
|
+
// => 'data:text/html,%3Cdiv%3E%3Cimg%3E%3C/div%3E'
|
|
82
84
|
|
|
83
85
|
console.log(decodeURIComponent(res4));
|
|
84
86
|
// => 'data:text/html,<div><img></div>'
|
|
@@ -152,7 +154,7 @@ Type: [object][3]
|
|
|
152
154
|
* `valid` **[boolean][2]** Is valid URI.
|
|
153
155
|
* `data` **[object][3]** Parsed result of data URL, `null`able.
|
|
154
156
|
* `data.mime` **[string][1]** MIME type.
|
|
155
|
-
* `data.base64` **[boolean][2]**
|
|
157
|
+
* `data.base64` **[boolean][2]** Is base64 encoded.
|
|
156
158
|
* `data.data` **[string][1]** Data part of the data URL.
|
|
157
159
|
* `href` **[string][1]** Sanitized URL input.
|
|
158
160
|
* `origin` **[string][1]** Scheme, domain and port of the sanitized URL.
|
|
@@ -196,12 +198,12 @@ const res3 = await parseURL('data:image/svg+xml;base64,PHN2Zz48ZyBvbmNsaWNrPSJhb
|
|
|
196
198
|
data: {
|
|
197
199
|
mime: 'image/svg+xml',
|
|
198
200
|
base64: false,
|
|
199
|
-
data: '%3Csvg%3E%3Cg%3E%3C%
|
|
201
|
+
data: '%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E'
|
|
200
202
|
},
|
|
201
|
-
href: 'data:image/svg+xml,%3Csvg%3E%3Cg%3E%3C%
|
|
203
|
+
href: 'data:image/svg+xml,%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E',
|
|
202
204
|
origin: 'null',
|
|
203
205
|
protocol: 'data:',
|
|
204
|
-
pathname: 'image/svg+xml,%3Csvg%3E%3Cg%3E%3C%
|
|
206
|
+
pathname: 'image/svg+xml,%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E',
|
|
205
207
|
...
|
|
206
208
|
} */
|
|
207
209
|
|
|
@@ -231,7 +233,7 @@ Synchronous version of the [parseURL()](#parseURL).
|
|
|
231
233
|
|
|
232
234
|
## isURI(uri)
|
|
233
235
|
|
|
234
|
-
Verify if the given URI is valid.
|
|
236
|
+
Verify if the given URI is valid and registered.
|
|
235
237
|
|
|
236
238
|
### Parameters
|
|
237
239
|
|
|
@@ -239,6 +241,7 @@ Verify if the given URI is valid.
|
|
|
239
241
|
|
|
240
242
|
Returns **[Promise][5]<[boolean][2]>** Result.
|
|
241
243
|
* Always `true` for `web+*` and `ext+*` schemes, except `web+javascript`, `web+vbscript`, `ext+javascript`, `ext+vbscript`.
|
|
244
|
+
* `false` for `javascript` and `vbscript` schemes.
|
|
242
245
|
|
|
243
246
|
```javascript
|
|
244
247
|
const res1 = await isURI('https://example.com/foo');
|
package/dist/url-sanitizer.js
CHANGED
|
@@ -1595,16 +1595,25 @@ var uri_schemes_default = [
|
|
|
1595
1595
|
// bundle/mjs/uri-util.js
|
|
1596
1596
|
var HEX = 16;
|
|
1597
1597
|
var REG_BASE64 = /^[\da-z+/\-_=]+$/i;
|
|
1598
|
-
var REG_DATA_URL = /data:[^,]
|
|
1598
|
+
var REG_DATA_URL = /data:[^,]*,/;
|
|
1599
1599
|
var REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\da-z+/\-_=]+/i;
|
|
1600
|
+
var REG_DATA_URL_G = /data:[^,]*,[^"]+/g;
|
|
1601
|
+
var REG_END_COLON = /:$/;
|
|
1602
|
+
var REG_END_NUM = /(?:#|%23)$/;
|
|
1603
|
+
var REG_END_QUEST = /(?<!(?:#|%23).*)(?:\?|%3F)$/;
|
|
1600
1604
|
var REG_HTML_SP = /[<>"'\s]/g;
|
|
1601
|
-
var
|
|
1602
|
-
var
|
|
1605
|
+
var REG_HTML_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;
|
|
1606
|
+
var REG_HTML_URL_ENC_SHORT = /%(?:2(?:2|7)|3(?:C|E))+?/;
|
|
1603
1607
|
var REG_MIME_DOM = /^(?:text\/(?:ht|x)ml|application\/(?:xhtml\+)?xml|image\/svg\+xml)/;
|
|
1608
|
+
var REG_NUM_DECI = /^\d+/;
|
|
1609
|
+
var REG_NUM_HEAD = /#x?$/;
|
|
1610
|
+
var REG_NUM_HEAD_ASCII = /^#(?:x(?:00)?[2-7]|\d)/;
|
|
1611
|
+
var REG_NUM_HEX = /^x[\dA-F]+/i;
|
|
1604
1612
|
var REG_NUM_REF = /&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig;
|
|
1605
1613
|
var REG_SCHEME = /^[a-z][\da-z+\-.]*$/;
|
|
1606
1614
|
var REG_SCHEME_CUSTOM = /^(?:ext|web)\+[a-z]+$/;
|
|
1607
1615
|
var REG_SCRIPT = /(?:java|vb)script/;
|
|
1616
|
+
var REG_SCRIPT_BLOB = /(?:java|vb)script|blob/;
|
|
1608
1617
|
var REG_URL_ENC = /^%[\dA-F]{2}$/i;
|
|
1609
1618
|
var REG_URL_ENC_AMP = /%26/g;
|
|
1610
1619
|
var getURLEncodedString = (str) => {
|
|
@@ -1671,9 +1680,9 @@ var parseURLEncodedNumCharRef = (str, nest = 0) => {
|
|
|
1671
1680
|
for (const item of items) {
|
|
1672
1681
|
const [numCharRef, value] = item;
|
|
1673
1682
|
let num;
|
|
1674
|
-
if (
|
|
1683
|
+
if (REG_NUM_HEX.test(value)) {
|
|
1675
1684
|
num = parseInt(`0${value}`, HEX);
|
|
1676
|
-
} else if (
|
|
1685
|
+
} else if (REG_NUM_DECI.test(value)) {
|
|
1677
1686
|
num = parseInt(value);
|
|
1678
1687
|
}
|
|
1679
1688
|
if (Number.isInteger(num)) {
|
|
@@ -1684,7 +1693,7 @@ var parseURLEncodedNumCharRef = (str, nest = 0) => {
|
|
|
1684
1693
|
];
|
|
1685
1694
|
if (textCharCodes.has(num)) {
|
|
1686
1695
|
res = `${preNum}${String.fromCharCode(num)}${postNum}`;
|
|
1687
|
-
if (
|
|
1696
|
+
if (REG_NUM_HEAD.test(preNum) || REG_NUM_HEAD_ASCII.test(postNum)) {
|
|
1688
1697
|
res = parseURLEncodedNumCharRef(res, ++nest);
|
|
1689
1698
|
}
|
|
1690
1699
|
} else if (num < HEX * HEX) {
|
|
@@ -1752,7 +1761,7 @@ var URISchemes = class {
|
|
|
1752
1761
|
/**
|
|
1753
1762
|
* verify URI
|
|
1754
1763
|
*
|
|
1755
|
-
* @param {string} uri - URI
|
|
1764
|
+
* @param {string} uri - URI
|
|
1756
1765
|
* @returns {boolean} - result
|
|
1757
1766
|
*/
|
|
1758
1767
|
verify(uri) {
|
|
@@ -1760,7 +1769,7 @@ var URISchemes = class {
|
|
|
1760
1769
|
if (isString(uri)) {
|
|
1761
1770
|
try {
|
|
1762
1771
|
const { protocol } = new URL(uri);
|
|
1763
|
-
const scheme = protocol.replace(
|
|
1772
|
+
const scheme = protocol.replace(REG_END_COLON, "");
|
|
1764
1773
|
const schemeParts = scheme.split("+");
|
|
1765
1774
|
res = !REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme) || schemeParts.every((s) => this.#schemes.has(s));
|
|
1766
1775
|
} catch (e) {
|
|
@@ -1783,18 +1792,18 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1783
1792
|
this.#recurse = /* @__PURE__ */ new Set();
|
|
1784
1793
|
}
|
|
1785
1794
|
/**
|
|
1786
|
-
*
|
|
1795
|
+
* replace matched data URLs
|
|
1787
1796
|
*
|
|
1788
|
-
* @param {string}
|
|
1789
|
-
* @returns {string} -
|
|
1797
|
+
* @param {string} data - data URL
|
|
1798
|
+
* @returns {string} - replaced data URL
|
|
1790
1799
|
*/
|
|
1791
|
-
|
|
1792
|
-
if (!isString(
|
|
1793
|
-
throw new TypeError(`Expected String but got ${getType(
|
|
1800
|
+
replace(data) {
|
|
1801
|
+
if (!isString(data)) {
|
|
1802
|
+
throw new TypeError(`Expected String but got ${getType(data)}.`);
|
|
1794
1803
|
}
|
|
1795
|
-
let
|
|
1796
|
-
if (
|
|
1797
|
-
const matchedDataUrls =
|
|
1804
|
+
let replacedData = data;
|
|
1805
|
+
if (REG_DATA_URL.test(replacedData)) {
|
|
1806
|
+
const matchedDataUrls = replacedData.matchAll(REG_DATA_URL_G);
|
|
1798
1807
|
const items = [...matchedDataUrls].reverse();
|
|
1799
1808
|
for (const item of items) {
|
|
1800
1809
|
let [dataUrl] = item;
|
|
@@ -1808,24 +1817,41 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1808
1817
|
});
|
|
1809
1818
|
const { index } = item;
|
|
1810
1819
|
const [preDataUrl, postDataUrl] = [
|
|
1811
|
-
|
|
1812
|
-
|
|
1820
|
+
replacedData.substring(0, index),
|
|
1821
|
+
replacedData.substring(index + dataUrl.length)
|
|
1813
1822
|
];
|
|
1814
1823
|
if (parsedDataUrl) {
|
|
1815
|
-
|
|
1824
|
+
replacedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
|
|
1816
1825
|
} else {
|
|
1817
|
-
|
|
1826
|
+
replacedData = `${preDataUrl}${postDataUrl}`;
|
|
1818
1827
|
}
|
|
1819
1828
|
}
|
|
1820
1829
|
}
|
|
1821
|
-
return
|
|
1830
|
+
return replacedData;
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* purify URL encoded DOM
|
|
1834
|
+
*
|
|
1835
|
+
* @param {string} dom - DOM string
|
|
1836
|
+
* @returns {string} - purified DOM string
|
|
1837
|
+
*/
|
|
1838
|
+
purify(dom) {
|
|
1839
|
+
if (!isString(dom)) {
|
|
1840
|
+
throw new TypeError(`Expected String but got ${getType(dom)}.`);
|
|
1841
|
+
}
|
|
1842
|
+
let purifiedDom = import_dompurify.default.sanitize(decodeURIComponent(dom));
|
|
1843
|
+
if (purifiedDom && REG_DATA_URL.test(purifiedDom)) {
|
|
1844
|
+
purifiedDom = this.replace(purifiedDom);
|
|
1845
|
+
}
|
|
1846
|
+
purifiedDom = purifiedDom.replace(REG_END_NUM, "").replace(REG_END_QUEST, "");
|
|
1847
|
+
return encodeURI(purifiedDom);
|
|
1822
1848
|
}
|
|
1823
1849
|
/**
|
|
1824
1850
|
* sanitize URL
|
|
1825
|
-
* NOTE: `data` and
|
|
1826
|
-
* `javascript` and
|
|
1851
|
+
* NOTE: `blob`, `data` and `file` schemes must be explicitly allowed
|
|
1852
|
+
* `javascript` and `vbscript` schemes can not be allowed
|
|
1827
1853
|
*
|
|
1828
|
-
* @param {string} url - URL
|
|
1854
|
+
* @param {string} url - URL
|
|
1829
1855
|
* @param {object} opt - options
|
|
1830
1856
|
* @param {Array.<string>} opt.allow - array of allowed schemes
|
|
1831
1857
|
* @param {Array.<string>} opt.deny - array of denied schemes
|
|
@@ -1840,6 +1866,7 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1840
1866
|
}
|
|
1841
1867
|
const { allow, deny, only, remove } = opt ?? {};
|
|
1842
1868
|
const schemeMap = /* @__PURE__ */ new Map([
|
|
1869
|
+
["blob", false],
|
|
1843
1870
|
["data", false],
|
|
1844
1871
|
["file", false],
|
|
1845
1872
|
["javascrpt", false],
|
|
@@ -1855,7 +1882,7 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1855
1882
|
for (let item of items) {
|
|
1856
1883
|
if (isString(item)) {
|
|
1857
1884
|
item = item.trim();
|
|
1858
|
-
if (!
|
|
1885
|
+
if (!REG_SCRIPT_BLOB.test(item)) {
|
|
1859
1886
|
if (super.has(item)) {
|
|
1860
1887
|
schemeMap.set(item, true);
|
|
1861
1888
|
} else {
|
|
@@ -1879,7 +1906,7 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1879
1906
|
for (let item of items) {
|
|
1880
1907
|
if (isString(item)) {
|
|
1881
1908
|
item = item.trim();
|
|
1882
|
-
if (!
|
|
1909
|
+
if (!REG_SCRIPT_BLOB.test(item)) {
|
|
1883
1910
|
if (super.has(item)) {
|
|
1884
1911
|
schemeMap.set(item, true);
|
|
1885
1912
|
} else {
|
|
@@ -1910,7 +1937,7 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1910
1937
|
let sanitizedUrl;
|
|
1911
1938
|
if (super.verify(url)) {
|
|
1912
1939
|
const { hash, href, pathname, protocol, search } = new URL(url);
|
|
1913
|
-
const scheme = protocol.replace(
|
|
1940
|
+
const scheme = protocol.replace(REG_END_COLON, "");
|
|
1914
1941
|
const schemeParts = scheme.split("+");
|
|
1915
1942
|
let bool;
|
|
1916
1943
|
if (restrictScheme) {
|
|
@@ -1924,9 +1951,10 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1924
1951
|
}
|
|
1925
1952
|
}
|
|
1926
1953
|
if (bool) {
|
|
1927
|
-
|
|
1954
|
+
const isDataUrl = schemeParts.includes("data");
|
|
1955
|
+
let finalize;
|
|
1928
1956
|
let urlToSanitize = href;
|
|
1929
|
-
if (
|
|
1957
|
+
if (isDataUrl) {
|
|
1930
1958
|
const [head, ...body] = pathname.split(",");
|
|
1931
1959
|
const data = `${body.join(",")}${search}${hash}`;
|
|
1932
1960
|
const mediaType = head.split(";");
|
|
@@ -1934,58 +1962,32 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1934
1962
|
let parsedData = data;
|
|
1935
1963
|
if (isBase64) {
|
|
1936
1964
|
parsedData = parseBase64(data);
|
|
1937
|
-
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
}
|
|
1945
|
-
} catch (e) {
|
|
1965
|
+
}
|
|
1966
|
+
try {
|
|
1967
|
+
const decodedData = parseURLEncodedNumCharRef(parsedData);
|
|
1968
|
+
const { protocol: dataScheme } = new URL(decodedData.trim());
|
|
1969
|
+
const dataSchemeParts = dataScheme.replace(REG_END_COLON, "").split("+");
|
|
1970
|
+
if (dataSchemeParts.some((s) => REG_SCRIPT_BLOB.test(s))) {
|
|
1971
|
+
urlToSanitize = "";
|
|
1946
1972
|
}
|
|
1973
|
+
} catch (e) {
|
|
1947
1974
|
}
|
|
1948
|
-
const containsDataUrl =
|
|
1975
|
+
const containsDataUrl = REG_DATA_URL.test(parsedData);
|
|
1949
1976
|
if (parsedData !== data || containsDataUrl) {
|
|
1950
1977
|
if (containsDataUrl) {
|
|
1951
|
-
|
|
1952
|
-
const items = [...matchedDataUrls].reverse();
|
|
1953
|
-
for (const item of items) {
|
|
1954
|
-
let [dataUrl] = item;
|
|
1955
|
-
if (REG_DATA_URL_BASE64.test(dataUrl)) {
|
|
1956
|
-
[dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);
|
|
1957
|
-
}
|
|
1958
|
-
this.#nest++;
|
|
1959
|
-
this.#recurse.add(dataUrl);
|
|
1960
|
-
const parsedDataUrl = this.sanitize(dataUrl, {
|
|
1961
|
-
allow: ["data"]
|
|
1962
|
-
});
|
|
1963
|
-
if (parsedDataUrl) {
|
|
1964
|
-
const { index } = item;
|
|
1965
|
-
const [preDataUrl, postDataUrl] = [
|
|
1966
|
-
parsedData.substring(0, index),
|
|
1967
|
-
parsedData.substring(index + dataUrl.length)
|
|
1968
|
-
];
|
|
1969
|
-
parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
if (this.#recurse.has(url)) {
|
|
1973
|
-
this.#recurse.delete(url);
|
|
1974
|
-
} else {
|
|
1975
|
-
escapeHtml = true;
|
|
1976
|
-
}
|
|
1978
|
+
parsedData = this.replace(parsedData);
|
|
1977
1979
|
} else if (this.#recurse.has(url)) {
|
|
1978
1980
|
this.#recurse.delete(url);
|
|
1979
1981
|
} else {
|
|
1980
|
-
|
|
1982
|
+
finalize = true;
|
|
1981
1983
|
}
|
|
1982
1984
|
} else if (this.#recurse.has(url)) {
|
|
1983
1985
|
this.#recurse.delete(url);
|
|
1984
1986
|
} else {
|
|
1985
|
-
|
|
1987
|
+
finalize = true;
|
|
1986
1988
|
}
|
|
1987
|
-
if (REG_MIME_DOM.test(head)) {
|
|
1988
|
-
parsedData = this.purify(parsedData)
|
|
1989
|
+
if (!head || REG_MIME_DOM.test(head)) {
|
|
1990
|
+
parsedData = this.purify(parsedData);
|
|
1989
1991
|
}
|
|
1990
1992
|
if (urlToSanitize && parsedData) {
|
|
1991
1993
|
if (isBase64 && parsedData !== data) {
|
|
@@ -1996,18 +1998,18 @@ var URLSanitizer = class extends URISchemes {
|
|
|
1996
1998
|
urlToSanitize = "";
|
|
1997
1999
|
}
|
|
1998
2000
|
} else {
|
|
1999
|
-
|
|
2001
|
+
finalize = true;
|
|
2000
2002
|
}
|
|
2001
|
-
if (!
|
|
2002
|
-
const item =
|
|
2003
|
+
if (!isDataUrl && remove && REG_HTML_URL_ENC_SHORT.test(urlToSanitize)) {
|
|
2004
|
+
const item = REG_HTML_URL_ENC_SHORT.exec(urlToSanitize);
|
|
2003
2005
|
const { index } = item;
|
|
2004
2006
|
urlToSanitize = urlToSanitize.substring(0, index);
|
|
2005
2007
|
}
|
|
2006
2008
|
if (urlToSanitize) {
|
|
2007
2009
|
sanitizedUrl = urlToSanitize.replace(REG_HTML_SP, getURLEncodedString).replace(REG_URL_ENC_AMP, escapeURLEncodedHTMLChars);
|
|
2008
|
-
if (
|
|
2009
|
-
if (!
|
|
2010
|
-
sanitizedUrl = sanitizedUrl.replace(
|
|
2010
|
+
if (finalize) {
|
|
2011
|
+
if (!isDataUrl) {
|
|
2012
|
+
sanitizedUrl = sanitizedUrl.replace(REG_HTML_URL_ENC, escapeURLEncodedHTMLChars);
|
|
2011
2013
|
}
|
|
2012
2014
|
this.#nest = 0;
|
|
2013
2015
|
}
|
|
@@ -2027,7 +2029,7 @@ var URLSanitizer = class extends URISchemes {
|
|
|
2027
2029
|
* @property {boolean} valid - is valid URI
|
|
2028
2030
|
* @property {object} data - parsed result of data URL, `null`able
|
|
2029
2031
|
* @property {string} data.mime - MIME type
|
|
2030
|
-
* @property {boolean} data.base64 -
|
|
2032
|
+
* @property {boolean} data.base64 - is base64 encoded
|
|
2031
2033
|
* @property {string} data.data - data part of the data URL
|
|
2032
2034
|
* @property {string} href - sanitized URL input
|
|
2033
2035
|
* @property {string} origin - scheme, domain and port of the sanitized URL
|
|
@@ -2039,22 +2041,21 @@ var URLSanitizer = class extends URISchemes {
|
|
|
2039
2041
|
* @property {string} port - port number of the sanitized URL
|
|
2040
2042
|
* @property {string} pathname - path of the sanitized URL
|
|
2041
2043
|
* @property {string} search - query string of the sanitized URL
|
|
2042
|
-
* @property {object} searchParams - URLSearchParams object
|
|
2043
2044
|
* @property {string} hash - fragment identifier of the sanitized URL
|
|
2044
2045
|
*/
|
|
2045
2046
|
/**
|
|
2046
2047
|
* parse sanitized URL
|
|
2047
2048
|
*
|
|
2048
|
-
* @param {string} url - URL
|
|
2049
|
+
* @param {string} url - URL
|
|
2049
2050
|
* @param {object} opt - options
|
|
2050
|
-
* @returns {ParsedURL} - result with
|
|
2051
|
+
* @returns {ParsedURL} - result with additional props based on URL API
|
|
2051
2052
|
*/
|
|
2052
2053
|
parse(url, opt) {
|
|
2053
2054
|
if (!isString(url)) {
|
|
2054
2055
|
throw new TypeError(`Expected String but got ${getType(url)}.`);
|
|
2055
2056
|
}
|
|
2056
2057
|
const sanitizedUrl = this.sanitize(url, opt ?? {
|
|
2057
|
-
allow: ["data", "file"]
|
|
2058
|
+
allow: ["blob", "data", "file"]
|
|
2058
2059
|
});
|
|
2059
2060
|
const parsedUrl = /* @__PURE__ */ new Map([
|
|
2060
2061
|
["input", url]
|
|
@@ -2062,9 +2063,10 @@ var URLSanitizer = class extends URISchemes {
|
|
|
2062
2063
|
if (sanitizedUrl) {
|
|
2063
2064
|
const urlObj = new URL(sanitizedUrl);
|
|
2064
2065
|
const { pathname, protocol } = urlObj;
|
|
2065
|
-
const schemeParts = protocol.replace(
|
|
2066
|
+
const schemeParts = protocol.replace(REG_END_COLON, "").split("+");
|
|
2067
|
+
const isDataUrl = schemeParts.includes("data");
|
|
2066
2068
|
parsedUrl.set("valid", true);
|
|
2067
|
-
if (
|
|
2069
|
+
if (isDataUrl) {
|
|
2068
2070
|
const dataUrl = /* @__PURE__ */ new Map();
|
|
2069
2071
|
const [head, ...body] = pathname.split(",");
|
|
2070
2072
|
const data = `${body.join(",")}`;
|
|
@@ -2103,19 +2105,11 @@ var parseURL = async (url) => {
|
|
|
2103
2105
|
const res = await parseURLSync(url);
|
|
2104
2106
|
return res;
|
|
2105
2107
|
};
|
|
2106
|
-
var sanitizeURLSync = (url, opt) => {
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
});
|
|
2112
|
-
let res;
|
|
2113
|
-
if (parsedUrl) {
|
|
2114
|
-
const { href } = parsedUrl;
|
|
2115
|
-
res = href;
|
|
2116
|
-
}
|
|
2117
|
-
return res ?? null;
|
|
2118
|
-
};
|
|
2108
|
+
var sanitizeURLSync = (url, opt) => urlSanitizer.sanitize(url, opt ?? {
|
|
2109
|
+
allow: [],
|
|
2110
|
+
deny: [],
|
|
2111
|
+
only: []
|
|
2112
|
+
});
|
|
2119
2113
|
var sanitizeURL = async (url, opt) => {
|
|
2120
2114
|
const res = await sanitizeURLSync(url, opt);
|
|
2121
2115
|
return res;
|