url-sanitizer 0.4.1 → 0.4.3
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 +19 -13
- package/dist/url-sanitizer.js +112 -42
- package/dist/url-sanitizer.js.map +2 -2
- package/dist/url-sanitizer.min.js +1 -1
- package/dist/url-sanitizer.min.js.map +3 -3
- package/package.json +2 -2
- package/src/mjs/uri-util.js +126 -49
package/README.md
CHANGED
|
@@ -32,16 +32,15 @@ import urlSanitizer, {
|
|
|
32
32
|
|
|
33
33
|
Sanitize the given URL.
|
|
34
34
|
* `data` and `file` schemes must be explicitly allowed.
|
|
35
|
-
* `javascript` and `vbscript` schemes can not be allowed.
|
|
36
35
|
|
|
37
36
|
### Parameters
|
|
38
37
|
|
|
39
38
|
* `url` **[string][1]** URL input
|
|
40
|
-
* `opt` **[object][3]**
|
|
41
|
-
* `opt.allow` **[Array][4]<[string][1]>**
|
|
42
|
-
* `opt.deny` **[Array][4]<[string][1]>**
|
|
39
|
+
* `opt` **[object][3]** Options
|
|
40
|
+
* `opt.allow` **[Array][4]<[string][1]>** Array of allowed schemes, e.g. `['data']`
|
|
41
|
+
* `opt.deny` **[Array][4]<[string][1]>** Array of denied schemes, e.g. `['web+foo']`
|
|
43
42
|
|
|
44
|
-
Returns **[Promise][5]<[string][1]?>**
|
|
43
|
+
Returns **[Promise][5]<[string][1]?>** Sanitized URL, `null`able
|
|
45
44
|
|
|
46
45
|
```javascript
|
|
47
46
|
const res1 = await sanitizeURL('http://example.com/?<script>alert(1);</script>')
|
|
@@ -59,6 +58,11 @@ const res3 = await sanitizeURL(`data:text/html;base64,${base64data3}`, {
|
|
|
59
58
|
allow: ['data']
|
|
60
59
|
}).then(res => decodeURIComponent(res));
|
|
61
60
|
// -> 'data:text/html,<script>alert(1);</script>'
|
|
61
|
+
|
|
62
|
+
const res4 = await sanitizeURL('web+foo://example.com', {
|
|
63
|
+
deny: ['web+foo']
|
|
64
|
+
});
|
|
65
|
+
// -> null
|
|
62
66
|
```
|
|
63
67
|
|
|
64
68
|
## sanitizeURLSync
|
|
@@ -73,7 +77,7 @@ Determines whether the given URI is valid.
|
|
|
73
77
|
|
|
74
78
|
* `uri` **[string][1]** URI input
|
|
75
79
|
|
|
76
|
-
Returns **[Promise][5]<[boolean][2]>**
|
|
80
|
+
Returns **[Promise][5]<[boolean][2]>** Result
|
|
77
81
|
* Always `true` for `web+*` and `ext+*` schemes
|
|
78
82
|
|
|
79
83
|
```javascript
|
|
@@ -96,13 +100,15 @@ Synchronous version of the [isURI()](#isuriuri).
|
|
|
96
100
|
|
|
97
101
|
## urlSanitizer
|
|
98
102
|
|
|
103
|
+
Instance of the sanitizer.
|
|
104
|
+
|
|
99
105
|
### urlSanitizer.get()
|
|
100
106
|
|
|
101
107
|
Get an array of URI schemes registered at [iana.org](https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml "Uniform Resource Identifier (URI) Schemes").
|
|
102
108
|
* Historical schemes omitted.
|
|
103
109
|
* `moz-extension` scheme added.
|
|
104
110
|
|
|
105
|
-
Returns **[Array][4]<[string][1]>**
|
|
111
|
+
Returns **[Array][4]<[string][1]>** Array of registered URI schemes
|
|
106
112
|
|
|
107
113
|
```javascript
|
|
108
114
|
const schemes = urlSanitizer.get();
|
|
@@ -115,9 +121,9 @@ Check if the given scheme is registered.
|
|
|
115
121
|
|
|
116
122
|
#### Parameters
|
|
117
123
|
|
|
118
|
-
* `scheme` **[string][1]**
|
|
124
|
+
* `scheme` **[string][1]** Scheme
|
|
119
125
|
|
|
120
|
-
Returns **[boolean][2]**
|
|
126
|
+
Returns **[boolean][2]** Result
|
|
121
127
|
|
|
122
128
|
```javascript
|
|
123
129
|
const res1 = urlSanitizer.has('https');
|
|
@@ -134,9 +140,9 @@ Add a scheme to the list of URI schemes.
|
|
|
134
140
|
|
|
135
141
|
#### Parameters
|
|
136
142
|
|
|
137
|
-
* `scheme` **[string][1]**
|
|
143
|
+
* `scheme` **[string][1]** Scheme
|
|
138
144
|
|
|
139
|
-
Returns **[Array][4]<[string][1]>**
|
|
145
|
+
Returns **[Array][4]<[string][1]>** Array of registered URI schemes
|
|
140
146
|
|
|
141
147
|
```javascript
|
|
142
148
|
console.log(isURISync('foo'));
|
|
@@ -155,9 +161,9 @@ Remove a scheme from the list of URI schemes.
|
|
|
155
161
|
|
|
156
162
|
#### Parameters
|
|
157
163
|
|
|
158
|
-
* `scheme` **[string][1]**
|
|
164
|
+
* `scheme` **[string][1]** Scheme
|
|
159
165
|
|
|
160
|
-
Returns **[boolean][2]**
|
|
166
|
+
Returns **[boolean][2]** Result
|
|
161
167
|
* `true` if the scheme is successfully removed, `false` otherwise.
|
|
162
168
|
|
|
163
169
|
```javascript
|
package/dist/url-sanitizer.js
CHANGED
|
@@ -591,6 +591,14 @@ var uri_schemes_default = [
|
|
|
591
591
|
|
|
592
592
|
// src/mjs/uri-util.js
|
|
593
593
|
var HEX = 16;
|
|
594
|
+
var REG_CHARS = /[<>"'\s]/g;
|
|
595
|
+
var REG_DATA_URL = /data:[^,]*,[^"]+/g;
|
|
596
|
+
var REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\dA-Za-z+/\-_=]+/;
|
|
597
|
+
var REG_DATA_URL_HEADER = /data:[^,]*,/;
|
|
598
|
+
var REG_NUM_REF = /&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig;
|
|
599
|
+
var REG_SCHEME = /^[a-z][a-z0-9+\-.]*$/;
|
|
600
|
+
var REG_SCHEME_CUSTOM = /^(?:ext|web)\+[a-z]+$/;
|
|
601
|
+
var REG_SCRIPT = /(?:java|vb)script/;
|
|
594
602
|
var getUrlEncodedString = (str) => {
|
|
595
603
|
if (!isString(str)) {
|
|
596
604
|
throw new TypeError(`Expected String but got ${getType(str)}.`);
|
|
@@ -606,7 +614,7 @@ var escapeUrlEncodedHtmlChars = (ch) => {
|
|
|
606
614
|
if (/^%[\dA-F]{2}$/i.test(ch)) {
|
|
607
615
|
ch = ch.toUpperCase();
|
|
608
616
|
} else {
|
|
609
|
-
throw new Error(
|
|
617
|
+
throw new Error(`Invalid URL encoded character: ${ch}`);
|
|
610
618
|
}
|
|
611
619
|
} else {
|
|
612
620
|
throw new TypeError(`Expected String but got ${getType(ch)}.`);
|
|
@@ -631,6 +639,8 @@ var escapeUrlEncodedHtmlChars = (ch) => {
|
|
|
631
639
|
var parseBase64 = (data) => {
|
|
632
640
|
if (!isString(data)) {
|
|
633
641
|
throw new TypeError(`Expected String but got ${getType(data)}.`);
|
|
642
|
+
} else if (!/^[\dA-Za-z+/\-_=]+$/.test(data)) {
|
|
643
|
+
throw new Error(`Invalid base64 data: ${data}`);
|
|
634
644
|
}
|
|
635
645
|
const bin = atob(data);
|
|
636
646
|
const uint8arr = Uint8Array.from([...bin].map((c) => c.charCodeAt(0)));
|
|
@@ -643,6 +653,46 @@ var parseBase64 = (data) => {
|
|
|
643
653
|
}
|
|
644
654
|
return parsedData;
|
|
645
655
|
};
|
|
656
|
+
var parseUrlEncodedNumCharRef = (str, nest = 0) => {
|
|
657
|
+
if (!isString(str)) {
|
|
658
|
+
throw new TypeError(`Expected String but got ${getType(str)}.`);
|
|
659
|
+
}
|
|
660
|
+
if (!Number.isInteger(nest)) {
|
|
661
|
+
throw new TypeError(`Expected Number but got ${getType(nest)}.`);
|
|
662
|
+
} else if (nest > HEX) {
|
|
663
|
+
throw new Error("Character references nested too deeply.");
|
|
664
|
+
}
|
|
665
|
+
let res = decodeURIComponent(str);
|
|
666
|
+
if (/&#/.test(res)) {
|
|
667
|
+
const textChars = new Set(text_chars_default);
|
|
668
|
+
const items = [...res.matchAll(REG_NUM_REF)].reverse();
|
|
669
|
+
for (const item of items) {
|
|
670
|
+
const [numCharRef, value] = item;
|
|
671
|
+
let num;
|
|
672
|
+
if (/^x[\dA-F]+/i.test(value)) {
|
|
673
|
+
num = parseInt(`0${value}`, HEX);
|
|
674
|
+
} else if (/^[\d]+/.test(value)) {
|
|
675
|
+
num = parseInt(value);
|
|
676
|
+
}
|
|
677
|
+
if (Number.isInteger(num)) {
|
|
678
|
+
const { index } = item;
|
|
679
|
+
const [preNum, postNum] = [
|
|
680
|
+
res.substring(0, index),
|
|
681
|
+
res.substring(index + numCharRef.length)
|
|
682
|
+
];
|
|
683
|
+
if (textChars.has(num)) {
|
|
684
|
+
res = `${preNum}${String.fromCharCode(num)}${postNum}`;
|
|
685
|
+
if (/#x?$/.test(preNum) || /^#x?[\d]+/.test(postNum)) {
|
|
686
|
+
res = parseUrlEncodedNumCharRef(res, ++nest);
|
|
687
|
+
}
|
|
688
|
+
} else if (num < HEX * HEX) {
|
|
689
|
+
res = `${preNum}${postNum}`;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return res;
|
|
695
|
+
};
|
|
646
696
|
var URISchemes = class {
|
|
647
697
|
/* private fields */
|
|
648
698
|
#schemes;
|
|
@@ -682,7 +732,7 @@ var URISchemes = class {
|
|
|
682
732
|
add(scheme) {
|
|
683
733
|
if (!isString(scheme)) {
|
|
684
734
|
throw new TypeError(`Expected String but got ${getType(scheme)}.`);
|
|
685
|
-
} else if (
|
|
735
|
+
} else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {
|
|
686
736
|
throw new Error(`Invalid scheme: ${scheme}`);
|
|
687
737
|
}
|
|
688
738
|
this.#schemes.add(scheme);
|
|
@@ -710,7 +760,7 @@ var URISchemes = class {
|
|
|
710
760
|
const { protocol } = new URL(uri);
|
|
711
761
|
const scheme = protocol.replace(/:$/, "");
|
|
712
762
|
const schemeParts = scheme.split("+");
|
|
713
|
-
res =
|
|
763
|
+
res = !REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme) || schemeParts.every((s) => this.#schemes.has(s));
|
|
714
764
|
} catch (e) {
|
|
715
765
|
res = false;
|
|
716
766
|
}
|
|
@@ -744,23 +794,26 @@ var URLSanitizer = class extends URISchemes {
|
|
|
744
794
|
sanitize(url, opt = { allow: [], deny: [] }) {
|
|
745
795
|
if (this.#nest > HEX) {
|
|
746
796
|
this.#nest = 0;
|
|
747
|
-
throw new Error("
|
|
797
|
+
throw new Error("Data URLs nested too deeply.");
|
|
748
798
|
}
|
|
749
799
|
let sanitizedUrl;
|
|
750
800
|
if (super.isURI(url)) {
|
|
751
801
|
const { allow, deny } = opt ?? {};
|
|
752
|
-
const { href, pathname, protocol } = new URL(url);
|
|
802
|
+
const { hash, href, pathname, protocol, search } = new URL(url);
|
|
753
803
|
const scheme = protocol.replace(/:$/, "");
|
|
754
804
|
const schemeParts = scheme.split("+");
|
|
755
|
-
const schemeMap = /* @__PURE__ */ new Map([
|
|
805
|
+
const schemeMap = /* @__PURE__ */ new Map([
|
|
806
|
+
["data", false],
|
|
807
|
+
["file", false],
|
|
808
|
+
["javascrpt", false],
|
|
809
|
+
["vbscript", false]
|
|
810
|
+
]);
|
|
756
811
|
if (Array.isArray(allow) && allow.length) {
|
|
757
812
|
const items = Object.values(allow);
|
|
758
813
|
for (let item of items) {
|
|
759
814
|
if (isString(item)) {
|
|
760
815
|
item = item.trim();
|
|
761
|
-
if (
|
|
762
|
-
schemeMap.set(item, false);
|
|
763
|
-
} else if (item) {
|
|
816
|
+
if (!REG_SCRIPT.test(item)) {
|
|
764
817
|
schemeMap.set(item, true);
|
|
765
818
|
}
|
|
766
819
|
}
|
|
@@ -786,41 +839,51 @@ var URLSanitizer = class extends URISchemes {
|
|
|
786
839
|
}
|
|
787
840
|
if (bool) {
|
|
788
841
|
const [amp, lt, gt, quot, apos] = ["&", "<", ">", '"', "'"].map(getUrlEncodedString);
|
|
789
|
-
const regChars = /[<>"']/g;
|
|
790
842
|
const regAmp = new RegExp(amp, "g");
|
|
791
843
|
const regEncodedChars = new RegExp(`(${lt}|${gt}|${quot}|${apos})`, "g");
|
|
792
844
|
let escapeHtml;
|
|
793
845
|
let urlToSanitize = href;
|
|
794
846
|
if (schemeParts.includes("data")) {
|
|
795
|
-
const [header,
|
|
847
|
+
const [header, ...body] = pathname.split(",");
|
|
848
|
+
const data = `${body.join(",")}${search}${hash}`;
|
|
796
849
|
const mediaType = header.split(";");
|
|
797
|
-
|
|
798
|
-
if (
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
850
|
+
let parsedData = data;
|
|
851
|
+
if (mediaType[mediaType.length - 1] === "base64") {
|
|
852
|
+
mediaType.pop();
|
|
853
|
+
parsedData = parseBase64(data);
|
|
854
|
+
} else {
|
|
855
|
+
try {
|
|
856
|
+
const decodedData = parseUrlEncodedNumCharRef(parsedData);
|
|
857
|
+
const { protocol: dataScheme } = new URL(decodedData.trim());
|
|
858
|
+
const dataSchemeParts = dataScheme.replace(/:$/, "").split("+");
|
|
859
|
+
if (dataSchemeParts.some((s) => REG_SCRIPT.test(s))) {
|
|
860
|
+
urlToSanitize = "";
|
|
861
|
+
}
|
|
862
|
+
} catch (e) {
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const containsDataUrl = REG_DATA_URL_HEADER.test(parsedData);
|
|
866
|
+
if (parsedData !== data || containsDataUrl) {
|
|
867
|
+
if (containsDataUrl) {
|
|
868
|
+
const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);
|
|
869
|
+
const items = [...matchedDataUrls].reverse();
|
|
870
|
+
for (const item of items) {
|
|
871
|
+
let [dataUrl] = item;
|
|
872
|
+
if (REG_DATA_URL_BASE64.test(dataUrl)) {
|
|
873
|
+
[dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);
|
|
874
|
+
}
|
|
875
|
+
this.#nest++;
|
|
876
|
+
this.#recurse.add(dataUrl);
|
|
877
|
+
const parsedDataUrl = this.sanitize(dataUrl, {
|
|
878
|
+
allow: ["data"]
|
|
879
|
+
});
|
|
880
|
+
if (parsedDataUrl) {
|
|
881
|
+
const { index } = item;
|
|
882
|
+
const [preDataUrl, postDataUrl] = [
|
|
883
|
+
parsedData.substring(0, index),
|
|
884
|
+
parsedData.substring(index + dataUrl.length)
|
|
885
|
+
];
|
|
886
|
+
parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
|
|
824
887
|
}
|
|
825
888
|
}
|
|
826
889
|
if (this.#recurse.has(url)) {
|
|
@@ -828,10 +891,12 @@ var URLSanitizer = class extends URISchemes {
|
|
|
828
891
|
} else {
|
|
829
892
|
escapeHtml = true;
|
|
830
893
|
}
|
|
831
|
-
|
|
894
|
+
} else if (this.#recurse.has(url)) {
|
|
895
|
+
this.#recurse.delete(url);
|
|
832
896
|
} else {
|
|
833
897
|
escapeHtml = true;
|
|
834
898
|
}
|
|
899
|
+
urlToSanitize = `${scheme}:${mediaType.join(";")},${parsedData}`;
|
|
835
900
|
} else if (this.#recurse.has(url)) {
|
|
836
901
|
this.#recurse.delete(url);
|
|
837
902
|
} else {
|
|
@@ -840,9 +905,14 @@ var URLSanitizer = class extends URISchemes {
|
|
|
840
905
|
} else {
|
|
841
906
|
escapeHtml = true;
|
|
842
907
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
908
|
+
if (urlToSanitize) {
|
|
909
|
+
sanitizedUrl = urlToSanitize.replace(REG_CHARS, getUrlEncodedString).replace(regAmp, escapeUrlEncodedHtmlChars);
|
|
910
|
+
if (escapeHtml) {
|
|
911
|
+
sanitizedUrl = sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);
|
|
912
|
+
this.#nest = 0;
|
|
913
|
+
}
|
|
914
|
+
} else {
|
|
915
|
+
sanitizedUrl = urlToSanitize;
|
|
846
916
|
this.#nest = 0;
|
|
847
917
|
}
|
|
848
918
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/mjs/common.js", "../src/lib/file/text-chars.json", "../src/lib/iana/uri-schemes.json", "../src/mjs/uri-util.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textCharTable from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (/^%[\\dA-F]{2}$/i.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`${ch} is not a URL encoded character.`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64\n *\n * @param {string} data - base64 data\n * @returns {string} - parsed data / base64 data\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textChars = new Set(textCharTable);\n let parsedData;\n if (uint8arr.every(c => textChars.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (/(?:java|vb)script/.test(scheme) ||\n !/^[a-z][a-z0-9+\\-.]*$/.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = /^(?:ext|web)\\+[a-z]+$/.test(scheme) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n}\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('The nesting of data URLs is too deep.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { href, pathname, protocol } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([['data', false], ['file', false]]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (/(?:java|vb)script/.test(item)) {\n schemeMap.set(item, false);\n } else if (item) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n const [amp, lt, gt, quot, apos] =\n ['&', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n const regChars = /[<>\"']/g;\n const regAmp = new RegExp(amp, 'g');\n const regEncodedChars =\n new RegExp(`(${lt}|${gt}|${quot}|${apos})`, 'g');\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [header, data] = pathname.split(',');\n const mediaType = header.split(';');\n const isBase64 = mediaType.pop() === 'base64';\n if (isBase64) {\n let parsedData = parseBase64(data);\n if (parsedData !== data) {\n if (/data:[^,]*,/.test(parsedData)) {\n const regDataUrl = /data:[^,]*,[^\"]+/g;\n const regBase64DataUrl = /data:[^,]*;?base64,[\\dA-Za-z+/\\-_=]+/;\n const matchedDataUrls = parsedData.matchAll(regDataUrl);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (regBase64DataUrl.test(dataUrl)) {\n [dataUrl] = regBase64DataUrl.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [beforeDataUrl, afterDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData =\n `${beforeDataUrl}${parsedDataUrl}${afterDataUrl}`;\n }\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n sanitizedUrl = urlToSanitize.replace(regChars, getUrlEncodedString)\n .replace(regAmp, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl =\n sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n}\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
|
|
5
|
-
"mappings": ";AAKA,IAAM,YAAY;AAClB,IAAM,UAAU;AAQT,IAAM,UAAU,OACrB,OAAO,UAAU,SAAS,KAAK,CAAC,EAAE,MAAM,WAAW,OAAO;AAQrD,IAAM,WAAW,OAAK,OAAO,MAAM,YAAY,aAAa;;;ACvBnE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACjVA,IAAM,MAAM;AAQL,IAAM,sBAAsB,SAAO;AACxC,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,UAAM,IAAI,UAAU,2BAA2B,QAAQ,GAAG,IAAI;AAAA,EAChE;AACA,QAAM,QAAQ,CAAC;AACf,aAAW,MAAM,KAAK;AACpB,UAAM,KAAK,IAAI,GAAG,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,YAAY,GAAG;AAAA,EAC/D;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAQO,IAAM,4BAA4B,QAAM;AAC7C,MAAI,SAAS,EAAE,GAAG;AAChB,QAAI,iBAAiB,KAAK,EAAE,GAAG;AAC7B,WAAK,GAAG,YAAY;AAAA,IACtB,OAAO;AACL,YAAM,IAAI,MAAM,GAAG,oCAAoC;AAAA,IACzD;AAAA,EACF,OAAO;AACL,UAAM,IAAI,UAAU,2BAA2B,QAAQ,EAAE,IAAI;AAAA,EAC/D;AACA,QAAM,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,IACjC,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,IAAI,mBAAmB;AACxD,MAAI;AACJ,MAAI,OAAO,KAAK;AACd,kBAAc,GAAG;AAAA,EACnB,WAAW,OAAO,IAAI;AACpB,kBAAc,GAAG;AAAA,EACnB,WAAW,OAAO,IAAI;AACpB,kBAAc,GAAG;AAAA,EACnB,WAAW,OAAO,MAAM;AACtB,kBAAc,GAAG;AAAA,EACnB,WAAW,OAAO,MAAM;AACtB,kBAAc,GAAG,MAAM;AAAA,EACzB,OAAO;AACL,kBAAc;AAAA,EAChB;AACA,SAAO;AACT;AAQO,IAAM,cAAc,UAAQ;AACjC,MAAI,CAAC,SAAS,IAAI,GAAG;AACnB,UAAM,IAAI,UAAU,2BAA2B,QAAQ,IAAI,IAAI;AAAA,EACjE;AACA,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,WAAW,WAAW,KAAK,CAAC,GAAG,GAAG,EAAE,IAAI,OAAK,EAAE,WAAW,CAAC,CAAC,CAAC;AACnE,QAAM,YAAY,IAAI,IAAI,kBAAa;AACvC,MAAI;AACJ,MAAI,SAAS,MAAM,OAAK,UAAU,IAAI,CAAC,CAAC,GAAG;AACzC,iBAAa,IAAI,QAAQ,OAAO,mBAAmB;AAAA,EACrD,OAAO;AACL,iBAAa;AAAA,EACf;AACA,SAAO;AACT;AAMO,IAAM,aAAN,MAAiB;AAAA;AAAA,EAEtB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,SAAK,WAAW,IAAI,IAAI,mBAAU;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM;AACJ,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,QAAQ;AACV,WAAO,KAAK,SAAS,IAAI,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,QAAQ;AACV,QAAI,CAAC,SAAS,MAAM,GAAG;AACrB,YAAM,IAAI,UAAU,2BAA2B,QAAQ,MAAM,IAAI;AAAA,IACnE,WAAW,oBAAoB,KAAK,MAAM,KAC/B,CAAC,uBAAuB,KAAK,MAAM,GAAG;AAC/C,YAAM,IAAI,MAAM,mBAAmB,QAAQ;AAAA,IAC7C;AACA,SAAK,SAAS,IAAI,MAAM;AACxB,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAQ;AACb,WAAO,KAAK,SAAS,OAAO,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK;AACT,QAAI;AACJ,QAAI,SAAS,GAAG,GAAG;AACjB,UAAI;AACF,cAAM,EAAE,SAAS,IAAI,IAAI,IAAI,GAAG;AAChC,cAAM,SAAS,SAAS,QAAQ,MAAM,EAAE;AACxC,cAAM,cAAc,OAAO,MAAM,GAAG;AACpC,cAAM,wBAAwB,KAAK,MAAM,KACnC,YAAY,MAAM,OAAK,KAAK,SAAS,IAAI,CAAC,CAAC;AAAA,MACnD,SAAS,GAAP;AACA,cAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,CAAC,CAAC;AAAA,EACX;AACF;AAGO,IAAM,eAAN,cAA2B,WAAW;AAAA;AAAA,EAE3C;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,UAAM;AACN,SAAK,QAAQ;AACb,SAAK,WAAW,oBAAI,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,SAAS,KAAK,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG;AAC3C,QAAI,KAAK,QAAQ,KAAK;AACpB,WAAK,QAAQ;AACb,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,QAAI;AACJ,QAAI,MAAM,MAAM,GAAG,GAAG;AACpB,YAAM,EAAE,OAAO,KAAK,IAAI,OAAO,CAAC;AAChC,YAAM,EAAE,MAAM,UAAU,SAAS,IAAI,IAAI,IAAI,GAAG;AAChD,YAAM,SAAS,SAAS,QAAQ,MAAM,EAAE;AACxC,YAAM,cAAc,OAAO,MAAM,GAAG;AACpC,YAAM,YAAY,oBAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC5D,UAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,QAAQ;AACxC,cAAM,QAAQ,OAAO,OAAO,KAAK;AACjC,iBAAS,QAAQ,OAAO;AACtB,cAAI,SAAS,IAAI,GAAG;AAClB,mBAAO,KAAK,KAAK;AACjB,gBAAI,oBAAoB,KAAK,IAAI,GAAG;AAClC,wBAAU,IAAI,MAAM,KAAK;AAAA,YAC3B,WAAW,MAAM;AACf,wBAAU,IAAI,MAAM,IAAI;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,QAAQ;AACtC,cAAM,QAAQ,OAAO,OAAO,IAAI;AAChC,iBAAS,QAAQ,OAAO;AACtB,cAAI,SAAS,IAAI,GAAG;AAClB,mBAAO,KAAK,KAAK;AACjB,gBAAI,MAAM;AACR,wBAAU,IAAI,MAAM,KAAK;AAAA,YAC3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI;AACJ,iBAAW,CAAC,KAAK,KAAK,KAAK,UAAU,QAAQ,GAAG;AAC9C,eAAO,SAAU,WAAW,OAAO,YAAY,MAAM,OAAK,MAAM,GAAG;AACnE,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM;AACR,cAAM,CAAC,KAAK,IAAI,IAAI,MAAM,IAAI,IAC5B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,IAAI,mBAAmB;AACnD,cAAM,WAAW;AACjB,cAAM,SAAS,IAAI,OAAO,KAAK,GAAG;AAClC,cAAM,kBACJ,IAAI,OAAO,IAAI,MAAM,MAAM,QAAQ,SAAS,GAAG;AACjD,YAAI;AACJ,YAAI,gBAAgB;AACpB,YAAI,YAAY,SAAS,MAAM,GAAG;AAChC,gBAAM,CAAC,QAAQ,IAAI,IAAI,SAAS,MAAM,GAAG;AACzC,gBAAM,YAAY,OAAO,MAAM,GAAG;AAClC,gBAAM,WAAW,UAAU,IAAI,MAAM;AACrC,cAAI,UAAU;AACZ,gBAAI,aAAa,YAAY,IAAI;AACjC,gBAAI,eAAe,MAAM;AACvB,kBAAI,cAAc,KAAK,UAAU,GAAG;AAClC,sBAAM,aAAa;AACnB,sBAAM,mBAAmB;AACzB,sBAAM,kBAAkB,WAAW,SAAS,UAAU;AACtD,sBAAM,QAAQ,CAAC,GAAG,eAAe,EAAE,QAAQ;AAC3C,2BAAW,QAAQ,OAAO;AACxB,sBAAI,CAAC,OAAO,IAAI;AAChB,sBAAI,iBAAiB,KAAK,OAAO,GAAG;AAClC,qBAAC,OAAO,IAAI,iBAAiB,KAAK,OAAO;AAAA,kBAC3C;AACA,uBAAK;AACL,uBAAK,SAAS,IAAI,OAAO;AACzB,wBAAM,gBAAgB,KAAK,SAAS,SAAS;AAAA,oBAC3C,OAAO,CAAC,MAAM;AAAA,kBAChB,CAAC;AACD,sBAAI,eAAe;AACjB,0BAAM,EAAE,MAAM,IAAI;AAClB,0BAAM,CAAC,eAAe,YAAY,IAAI;AAAA,sBACpC,WAAW,UAAU,GAAG,KAAK;AAAA,sBAC7B,WAAW,UAAU,QAAQ,QAAQ,MAAM;AAAA,oBAC7C;AACA,iCACE,GAAG,gBAAgB,gBAAgB;AAAA,kBACvC;AAAA,gBACF;AAAA,cACF;AACA,kBAAI,KAAK,SAAS,IAAI,GAAG,GAAG;AAC1B,qBAAK,SAAS,OAAO,GAAG;AAAA,cAC1B,OAAO;AACL,6BAAa;AAAA,cACf;AACA,8BAAgB,GAAG,UAAU,UAAU,KAAK,GAAG,KAAK;AAAA,YACtD,OAAO;AACL,2BAAa;AAAA,YACf;AAAA,UACF,WAAW,KAAK,SAAS,IAAI,GAAG,GAAG;AACjC,iBAAK,SAAS,OAAO,GAAG;AAAA,UAC1B,OAAO;AACL,yBAAa;AAAA,UACf;AAAA,QACF,OAAO;AACL,uBAAa;AAAA,QACf;AACA,uBAAe,cAAc,QAAQ,UAAU,mBAAmB,EAC/D,QAAQ,QAAQ,yBAAyB;AAC5C,YAAI,YAAY;AACd,yBACE,aAAa,QAAQ,iBAAiB,yBAAyB;AACjE,eAAK,QAAQ;AAAA,QACf;AAAA,MACF;AAAA,IACF;AACA,WAAO,gBAAgB;AAAA,EACzB;AACF;AAGA,IAAM,eAAe,IAAI,aAAa;AAStC,IAAM,QAAQ,SAAO,aAAa,MAAM,GAAG;AAQpC,IAAM,QAAQ,OAAM,QAAO;AAChC,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,SAAO;AACT;AASA,IAAM,cAAc,CAAC,KAAK,QAAQ,aAAa,SAAS,KAAK,OAAO;AAAA,EAClE,OAAO,CAAC;AAAA,EACR,MAAM,CAAC;AACT,CAAC;AASM,IAAM,cAAc,OAAO,KAAK,QAAQ;AAC7C,QAAM,MAAM,MAAM,YAAY,KAAK,GAAG;AACtC,SAAO;AACT;",
|
|
4
|
+
"sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textCharTable from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_CHARS = /[<>\"'\\s]/g;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\dA-Za-z+/\\-_=]+/;\nconst REG_DATA_URL_HEADER = /data:[^,]*,/;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][a-z0-9+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (/^%[\\dA-F]{2}$/i.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!/^[\\dA-Za-z+/\\-_=]+$/.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textChars = new Set(textCharTable);\n let parsedData;\n if (uint8arr.every(c => textChars.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textChars = new Set(textCharTable);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textChars.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#x?[\\d]+/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n}\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n const [amp, lt, gt, quot, apos] =\n ['&', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n const regAmp = new RegExp(amp, 'g');\n const regEncodedChars =\n new RegExp(`(${lt}|${gt}|${quot}|${apos})`, 'g');\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [header, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = header.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = REG_DATA_URL_HEADER.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize.replace(REG_CHARS, getUrlEncodedString)\n .replace(regAmp, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl =\n sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n}\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
|
|
5
|
+
"mappings": ";AAKA,IAAM,YAAY;AAClB,IAAM,UAAU;AAQT,IAAM,UAAU,OACrB,OAAO,UAAU,SAAS,KAAK,CAAC,EAAE,MAAM,WAAW,OAAO;AAQrD,IAAM,WAAW,OAAK,OAAO,MAAM,YAAY,aAAa;;;ACvBnE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACjVA,IAAM,MAAM;AACZ,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,sBAA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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var g=
|
|
1
|
+
var g=t=>Object.prototype.toString.call(t).slice(8,-1),p=t=>typeof t=="string"||t instanceof String;var C=[7,8,9,10,11,12,13,27,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];var G=["aaa","aaas","about","acap","acct","acd","acr","adiumxtra","adt","afp","afs","aim","amss","android","appdata","apt","ar","ark","attachment","aw","barion","beshare","bitcoin","bitcoincash","blob","bolo","browserext","cabal","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cvs","dab","dat","data","dav","diaspora","dict","did","dis","dlna-playcontainer","dlna-playsingle","dns","dntp","doi","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","ethereum","example","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gtalk","h323","ham","hcap","hcp","http","https","hxxp","hxxps","hydrazone","hyper","iax","icap","icon","im","imap","info","iotdisco","ipfs","ipn","ipns","ipp","ipps","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lorawan","lpa","lvlt","magnet","mailto","maps","market","matrix","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-powerpoint","ms-project","ms-publisher","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mumble","mupdate","mvn","news","nfs","ni","nih","nntp","notes","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openpgp4fpr","otpauth","palm","paparazzi","payment","payto","pkcs11","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","sarif","secondlife","secret-token","service","session","sftp","sgn","shc","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spiffe","spotify","ssb","ssh","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","tel","teliaeid","telnet","tftp","things","thismessage","tip","tn3270","tool","turn","turns","tv","udp","unreal","urn","ut2004","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcon","xcon-userid","xfire","xmlrpc.beep","xmlrpc.beeps","xmpp","xri","ymsgr","z39.50r","z39.50s"];var u=16,te=/[<>"'\s]/g,se=/data:[^,]*,[^"]+/g,M=/data:[^,]*;?base64,[\dA-Za-z+/\-_=]+/,re=/data:[^,]*,/,ae=/&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig,ie=/^[a-z][a-z0-9+\-.]*$/,oe=/^(?:ext|web)\+[a-z]+$/,E=/(?:java|vb)script/,$=t=>{if(!p(t))throw new TypeError(`Expected String but got ${g(t)}.`);let e=[];for(let s of t)e.push(`%${s.charCodeAt(0).toString(u).toUpperCase()}`);return e.join("")},O=t=>{if(p(t))if(/^%[\dA-F]{2}$/i.test(t))t=t.toUpperCase();else throw new Error(`Invalid URL encoded character: ${t}`);else throw new TypeError(`Expected String but got ${g(t)}.`);let[e,s,i,r,o,f]=["&","#","<",">",'"',"'"].map($),n;return t===e?n=`${e}amp;`:t===i?n=`${e}lt;`:t===r?n=`${e}gt;`:t===o?n=`${e}quot;`:t===f?n=`${e}${s}39;`:n=t,n},ne=t=>{if(p(t)){if(!/^[\dA-Za-z+/\-_=]+$/.test(t))throw new Error(`Invalid base64 data: ${t}`)}else throw new TypeError(`Expected String but got ${g(t)}.`);let e=atob(t),s=Uint8Array.from([...e].map(o=>o.charCodeAt(0))),i=new Set(C),r;return s.every(o=>i.has(o))?r=e.replace(/\s/g,$):r=t,r},H=(t,e=0)=>{if(!p(t))throw new TypeError(`Expected String but got ${g(t)}.`);if(Number.isInteger(e)){if(e>u)throw new Error("Character references nested too deeply.")}else throw new TypeError(`Expected Number but got ${g(e)}.`);let s=decodeURIComponent(t);if(/&#/.test(s)){let i=new Set(C),r=[...s.matchAll(ae)].reverse();for(let o of r){let[f,n]=o,m;if(/^x[\dA-F]+/i.test(n)?m=parseInt(`0${n}`,u):/^[\d]+/.test(n)&&(m=parseInt(n)),Number.isInteger(m)){let{index:x}=o,[w,h]=[s.substring(0,x),s.substring(x+f.length)];i.has(m)?(s=`${w}${String.fromCharCode(m)}${h}`,(/#x?$/.test(w)||/^#x?[\d]+/.test(h))&&(s=H(s,++e))):m<u*u&&(s=`${w}${h}`)}}}return s},_=class{#e;constructor(){this.#e=new Set(G)}get(){return[...this.#e]}has(e){return this.#e.has(e)}add(e){if(p(e)){if(E.test(e)||!ie.test(e))throw new Error(`Invalid scheme: ${e}`)}else throw new TypeError(`Expected String but got ${g(e)}.`);return this.#e.add(e),[...this.#e]}remove(e){return this.#e.delete(e)}isURI(e){let s;if(p(e))try{let{protocol:i}=new URL(e),r=i.replace(/:$/,""),o=r.split("+");s=!E.test(r)&&oe.test(r)||o.every(f=>this.#e.has(f))}catch{s=!1}return!!s}},j=class extends _{#e;#t;constructor(){super(),this.#e=0,this.#t=new Set}sanitize(e,s={allow:[],deny:[]}){if(this.#e>u)throw this.#e=0,new Error("Data URLs nested too deeply.");let i;if(super.isURI(e)){let{allow:r,deny:o}=s??{},{hash:f,href:n,pathname:m,protocol:x,search:w}=new URL(e),h=x.replace(/:$/,""),D=h.split("+"),R=new Map([["data",!1],["file",!1],["javascrpt",!1],["vbscript",!1]]);if(Array.isArray(r)&&r.length){let l=Object.values(r);for(let a of l)p(a)&&(a=a.trim(),E.test(a)||R.set(a,!0))}if(Array.isArray(o)&&o.length){let l=Object.values(o);for(let a of l)p(a)&&(a=a.trim(),a&&R.set(a,!1))}let U;for(let[l,a]of R.entries())if(U=a||h!==l&&D.every(S=>S!==l),!U)break;if(U){let[l,a,S,Y,B]=["&","<",">",'"',"'"].map($),Z=new RegExp(l,"g"),X=new RegExp(`(${a}|${S}|${Y}|${B})`,"g"),b,y=n;if(D.includes("data")){let[J,...K]=m.split(","),k=`${K.join(",")}${w}${f}`,v=J.split(";"),c=k;if(v[v.length-1]==="base64")v.pop(),c=ne(k);else try{let z=H(c),{protocol:A}=new URL(z.trim());A.replace(/:$/,"").split("+").some(d=>E.test(d))&&(y="")}catch{}let L=re.test(c);if(c!==k||L){if(L){let A=[...c.matchAll(se)].reverse();for(let T of A){let[d]=T;M.test(d)&&([d]=M.exec(d)),this.#e++,this.#t.add(d);let P=this.sanitize(d,{allow:["data"]});if(P){let{index:q}=T,[Q,V]=[c.substring(0,q),c.substring(q+d.length)];c=`${Q}${P}${V}`}}this.#t.has(e)?this.#t.delete(e):b=!0}else this.#t.has(e)?this.#t.delete(e):b=!0;y=`${h}:${v.join(";")},${c}`}else this.#t.has(e)?this.#t.delete(e):b=!0}else b=!0;y?(i=y.replace(te,$).replace(Z,O),b&&(i=i.replace(X,O),this.#e=0)):(i=y,this.#e=0)}}return i||null}},I=new j,N=t=>I.isURI(t),ce=async t=>await N(t),F=(t,e)=>I.sanitize(t,e??{allow:[],deny:[]}),pe=async(t,e)=>await F(t,e);export{I as default,ce as isURI,N as isURISync,pe as sanitizeURL,F as sanitizeURLSync};
|
|
2
2
|
//# sourceMappingURL=url-sanitizer.min.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/mjs/common.js", "../src/lib/file/text-chars.json", "../src/lib/iana/uri-schemes.json", "../src/mjs/uri-util.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textCharTable from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (/^%[\\dA-F]{2}$/i.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`${ch} is not a URL encoded character.`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64\n *\n * @param {string} data - base64 data\n * @returns {string} - parsed data / base64 data\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textChars = new Set(textCharTable);\n let parsedData;\n if (uint8arr.every(c => textChars.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (/(?:java|vb)script/.test(scheme) ||\n !/^[a-z][a-z0-9+\\-.]*$/.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = /^(?:ext|web)\\+[a-z]+$/.test(scheme) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n}\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('The nesting of data URLs is too deep.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { href, pathname, protocol } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([['data', false], ['file', false]]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (/(?:java|vb)script/.test(item)) {\n schemeMap.set(item, false);\n } else if (item) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n const [amp, lt, gt, quot, apos] =\n ['&', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n const regChars = /[<>\"']/g;\n const regAmp = new RegExp(amp, 'g');\n const regEncodedChars =\n new RegExp(`(${lt}|${gt}|${quot}|${apos})`, 'g');\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [header, data] = pathname.split(',');\n const mediaType = header.split(';');\n const isBase64 = mediaType.pop() === 'base64';\n if (isBase64) {\n let parsedData = parseBase64(data);\n if (parsedData !== data) {\n if (/data:[^,]*,/.test(parsedData)) {\n const regDataUrl = /data:[^,]*,[^\"]+/g;\n const regBase64DataUrl = /data:[^,]*;?base64,[\\dA-Za-z+/\\-_=]+/;\n const matchedDataUrls = parsedData.matchAll(regDataUrl);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (regBase64DataUrl.test(dataUrl)) {\n [dataUrl] = regBase64DataUrl.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [beforeDataUrl, afterDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData =\n `${beforeDataUrl}${parsedDataUrl}${afterDataUrl}`;\n }\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n sanitizedUrl = urlToSanitize.replace(regChars, getUrlEncodedString)\n .replace(regAmp, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl =\n sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n}\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
|
|
5
|
-
"mappings": "AAcO,IAAMA,EAAUC,GACrB,OAAO,UAAU,SAAS,KAAKA,CAAC,EAAE,MAAM,EAAW,EAAO,EAQ/CC,EAAWD,GAAK,OAAOA,GAAM,UAAYA,aAAa,OCvBnE,IAAAE,EAAA,CACE,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,GACF,ECxOA,IAAAC,EAAA,CACE,MACA,OACA,QACA,OACA,OACA,MACA,MACA,YACA,MACA,MACA,MACA,MACA,OACA,UACA,UACA,MACA,KACA,MACA,aACA,KACA,SACA,UACA,UACA,cACA,OACA,OACA,aACA,QACA,aACA,SACA,MACA,OACA,QACA,SACA,mBACA,MACA,OACA,QACA,0BACA,UACA,eACA,OACA,OACA,MACA,MACA,MACA,OACA,MACA,WACA,OACA,MACA,MACA,qBACA,kBACA,MACA,OACA,MACA,MACA,MACA,OACA,MACA,MACA,MACA,OACA,OACA,MACA,OACA,WACA,MACA,WACA,UACA,WACA,OACA,YACA,OACA,OACA,SACA,2BACA,OACA,KACA,MACA,cACA,MACA,KACA,MACA,SACA,eACA,KACA,SACA,QACA,QACA,OACA,MACA,OACA,MACA,OACA,QACA,OACA,QACA,YACA,QACA,MACA,OACA,OACA,KACA,OACA,OACA,WACA,OACA,MACA,OACA,MACA,OACA,MACA,OACA,OACA,OACA,YACA,WACA,WACA,YACA,WACA,OACA,SACA,MACA,MACA,UACA,SACA,OACA,OACA,QACA,gBACA,UACA,MACA,OACA,SACA,SACA,OACA,SACA,SACA,UACA,2BACA,uCACA,kCACA,MACA,MACA,UACA,MACA,gBACA,YACA,kBACA,uBACA,gBACA,cACA,gBACA,WACA,sBACA,qBACA,mBACA,eACA,UACA,cACA,cACA,gCACA,qBACA,aACA,yBACA,iBACA,sBACA,eACA,YACA,gBACA,aACA,eACA,0BACA,yBACA,gBACA,kBACA,YACA,mBACA,iCACA,4BACA,cACA,2BACA,wBACA,qBACA,uBACA,2BACA,iCACA,gCACA,+BACA,uBACA,uBACA,mBACA,8BACA,4BACA,oBACA,sBACA,wBACA,6BACA,mBACA,wBACA,SACA,cACA,gBACA,gBACA,qBACA,qBACA,WACA,aACA,gBACA,oBACA,UACA,QACA,OACA,QACA,MACA,KACA,OACA,SACA,UACA,MACA,OACA,MACA,KACA,MACA,OACA,QACA,MACA,MACA,MACA,UACA,cACA,kBACA,cACA,UACA,OACA,YACA,UACA,QACA,SACA,WACA,MACA,OACA,QACA,OACA,OACA,OACA,KACA,QACA,iBACA,QACA,SACA,SACA,MACA,WACA,MACA,QACA,QACA,OACA,OACA,QACA,QACA,QACA,aACA,eACA,UACA,UACA,OACA,MACA,MACA,QACA,eACA,UACA,MACA,OACA,QACA,MACA,MACA,MACA,OACA,OACA,YACA,aACA,SACA,SACA,UACA,MACA,MACA,WACA,QACA,OACA,QACA,SACA,MACA,MACA,OACA,WACA,MACA,QACA,YACA,MACA,WACA,SACA,OACA,SACA,cACA,MACA,SACA,OACA,OACA,QACA,KACA,MACA,SACA,MACA,SACA,kBACA,UACA,QACA,WACA,MACA,cACA,MACA,SACA,kBACA,OACA,KACA,MACA,OACA,SACA,OACA,KACA,MACA,OACA,UACA,OACA,cACA,QACA,cACA,eACA,OACA,MACA,QACA,UACA,SACF,ECjVA,IAAMC,EAAM,
|
|
6
|
-
"names": ["getType", "o", "isString", "text_chars_default", "uri_schemes_default", "HEX", "getUrlEncodedString", "str", "isString", "getType", "chars", "ch", "escapeUrlEncodedHtmlChars", "amp", "num", "lt", "gt", "quot", "apos", "escapedChar", "parseBase64", "data", "bin", "uint8arr", "c", "textChars", "text_chars_default", "parsedData", "URISchemes", "#schemes", "uri_schemes_default", "scheme", "uri", "
|
|
4
|
+
"sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textCharTable from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_CHARS = /[<>\"'\\s]/g;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\dA-Za-z+/\\-_=]+/;\nconst REG_DATA_URL_HEADER = /data:[^,]*,/;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][a-z0-9+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (/^%[\\dA-F]{2}$/i.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!/^[\\dA-Za-z+/\\-_=]+$/.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textChars = new Set(textCharTable);\n let parsedData;\n if (uint8arr.every(c => textChars.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textChars = new Set(textCharTable);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textChars.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#x?[\\d]+/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n}\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n const [amp, lt, gt, quot, apos] =\n ['&', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n const regAmp = new RegExp(amp, 'g');\n const regEncodedChars =\n new RegExp(`(${lt}|${gt}|${quot}|${apos})`, 'g');\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [header, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = header.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = REG_DATA_URL_HEADER.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize.replace(REG_CHARS, getUrlEncodedString)\n .replace(regAmp, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl =\n sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n}\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
|
|
5
|
+
"mappings": "AAcO,IAAMA,EAAUC,GACrB,OAAO,UAAU,SAAS,KAAKA,CAAC,EAAE,MAAM,EAAW,EAAO,EAQ/CC,EAAWD,GAAK,OAAOA,GAAM,UAAYA,aAAa,OCvBnE,IAAAE,EAAA,CACE,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,GACF,ECxOA,IAAAC,EAAA,CACE,MACA,OACA,QACA,OACA,OACA,MACA,MACA,YACA,MACA,MACA,MACA,MACA,OACA,UACA,UACA,MACA,KACA,MACA,aACA,KACA,SACA,UACA,UACA,cACA,OACA,OACA,aACA,QACA,aACA,SACA,MACA,OACA,QACA,SACA,mBACA,MACA,OACA,QACA,0BACA,UACA,eACA,OACA,OACA,MACA,MACA,MACA,OACA,MACA,WACA,OACA,MACA,MACA,qBACA,kBACA,MACA,OACA,MACA,MACA,MACA,OACA,MACA,MACA,MACA,OACA,OACA,MACA,OACA,WACA,MACA,WACA,UACA,WACA,OACA,YACA,OACA,OACA,SACA,2BACA,OACA,KACA,MACA,cACA,MACA,KACA,MACA,SACA,eACA,KACA,SACA,QACA,QACA,OACA,MACA,OACA,MACA,OACA,QACA,OACA,QACA,YACA,QACA,MACA,OACA,OACA,KACA,OACA,OACA,WACA,OACA,MACA,OACA,MACA,OACA,MACA,OACA,OACA,OACA,YACA,WACA,WACA,YACA,WACA,OACA,SACA,MACA,MACA,UACA,SACA,OACA,OACA,QACA,gBACA,UACA,MACA,OACA,SACA,SACA,OACA,SACA,SACA,UACA,2BACA,uCACA,kCACA,MACA,MACA,UACA,MACA,gBACA,YACA,kBACA,uBACA,gBACA,cACA,gBACA,WACA,sBACA,qBACA,mBACA,eACA,UACA,cACA,cACA,gCACA,qBACA,aACA,yBACA,iBACA,sBACA,eACA,YACA,gBACA,aACA,eACA,0BACA,yBACA,gBACA,kBACA,YACA,mBACA,iCACA,4BACA,cACA,2BACA,wBACA,qBACA,uBACA,2BACA,iCACA,gCACA,+BACA,uBACA,uBACA,mBACA,8BACA,4BACA,oBACA,sBACA,wBACA,6BACA,mBACA,wBACA,SACA,cACA,gBACA,gBACA,qBACA,qBACA,WACA,aACA,gBACA,oBACA,UACA,QACA,OACA,QACA,MACA,KACA,OACA,SACA,UACA,MACA,OACA,MACA,KACA,MACA,OACA,QACA,MACA,MACA,MACA,UACA,cACA,kBACA,cACA,UACA,OACA,YACA,UACA,QACA,SACA,WACA,MACA,OACA,QACA,OACA,OACA,OACA,KACA,QACA,iBACA,QACA,SACA,SACA,MACA,WACA,MACA,QACA,QACA,OACA,OACA,QACA,QACA,QACA,aACA,eACA,UACA,UACA,OACA,MACA,MACA,QACA,eACA,UACA,MACA,OACA,QACA,MACA,MACA,MACA,OACA,OACA,YACA,aACA,SACA,SACA,UACA,MACA,MACA,WACA,QACA,OACA,QACA,SACA,MACA,MACA,OACA,WACA,MACA,QACA,YACA,MACA,WACA,SACA,OACA,SACA,cACA,MACA,SACA,OACA,OACA,QACA,KACA,MACA,SACA,MACA,SACA,kBACA,UACA,QACA,WACA,MACA,cACA,MACA,SACA,kBACA,OACA,KACA,MACA,OACA,SACA,OACA,KACA,MACA,OACA,UACA,OACA,cACA,QACA,cACA,eACA,OACA,MACA,QACA,UACA,SACF,ECjVA,IAAMC,EAAM,GACNC,GAAY,YACZC,GAAe,oBACfC,EAAsB,uCACtBC,GAAsB,cACtBC,GAAc,uCACdC,GAAa,uBACbC,GAAoB,wBACpBC,EAAa,oBAQNC,EAAsBC,GAAO,CACxC,GAAI,CAACC,EAASD,CAAG,EACf,MAAM,IAAI,UAAU,2BAA2BE,EAAQF,CAAG,IAAI,EAEhE,IAAMG,EAAQ,CAAC,EACf,QAAWC,KAAMJ,EACfG,EAAM,KAAK,IAAIC,EAAG,WAAW,CAAC,EAAE,SAASd,CAAG,EAAE,YAAY,GAAG,EAE/D,OAAOa,EAAM,KAAK,EAAE,CACtB,EAQaE,EAA4BD,GAAM,CAC7C,GAAIH,EAASG,CAAE,EACb,GAAI,iBAAiB,KAAKA,CAAE,EAC1BA,EAAKA,EAAG,YAAY,MAEpB,OAAM,IAAI,MAAM,kCAAkCA,GAAI,MAGxD,OAAM,IAAI,UAAU,2BAA2BF,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",
|
|
6
|
+
"names": ["getType", "o", "isString", "text_chars_default", "uri_schemes_default", "HEX", "REG_CHARS", "REG_DATA_URL", "REG_DATA_URL_BASE64", "REG_DATA_URL_HEADER", "REG_NUM_REF", "REG_SCHEME", "REG_SCHEME_CUSTOM", "REG_SCRIPT", "getUrlEncodedString", "str", "isString", "getType", "chars", "ch", "escapeUrlEncodedHtmlChars", "amp", "num", "lt", "gt", "quot", "apos", "escapedChar", "parseBase64", "data", "bin", "uint8arr", "c", "textChars", "text_chars_default", "parsedData", "parseUrlEncodedNumCharRef", "nest", "res", "items", "item", "numCharRef", "value", "index", "preNum", "postNum", "URISchemes", "#schemes", "uri_schemes_default", "scheme", "uri", "protocol", "schemeParts", "s", "URLSanitizer", "#nest", "#recurse", "url", "opt", "sanitizedUrl", "allow", "deny", "hash", "href", "pathname", "search", "schemeMap", "bool", "key", "regAmp", "regEncodedChars", "escapeHtml", "urlToSanitize", "header", "body", "mediaType", "decodedData", "dataScheme", "containsDataUrl", "dataUrl", "parsedDataUrl", "preDataUrl", "postDataUrl", "urlSanitizer", "isUri", "isURI", "sanitizeUrl", "sanitizeURL"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"index.js"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "npm run include && npm run lint && npm test && npm run bundle",
|
|
23
|
+
"build": "npm run include && npm run char && npm run lint && npm test && npm run bundle",
|
|
24
24
|
"bundle": "npm-run-all -s bundle-*",
|
|
25
25
|
"bundle-src": "esbuild --format=esm --platform=browser --outfile=./dist/url-sanitizer.js --bundle --sourcemap ./index.js",
|
|
26
26
|
"bundle-min": "esbuild --format=esm --platform=browser --outfile=./dist/url-sanitizer.min.js --bundle --minify --sourcemap ./index.js",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"sinon": "^15.0.1",
|
|
51
51
|
"undici": "^5.16.0"
|
|
52
52
|
},
|
|
53
|
-
"version": "0.4.
|
|
53
|
+
"version": "0.4.3"
|
|
54
54
|
}
|
package/src/mjs/uri-util.js
CHANGED
|
@@ -9,6 +9,14 @@ import uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };
|
|
|
9
9
|
|
|
10
10
|
/* constants */
|
|
11
11
|
const HEX = 16;
|
|
12
|
+
const REG_CHARS = /[<>"'\s]/g;
|
|
13
|
+
const REG_DATA_URL = /data:[^,]*,[^"]+/g;
|
|
14
|
+
const REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\dA-Za-z+/\-_=]+/;
|
|
15
|
+
const REG_DATA_URL_HEADER = /data:[^,]*,/;
|
|
16
|
+
const REG_NUM_REF = /&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig;
|
|
17
|
+
const REG_SCHEME = /^[a-z][a-z0-9+\-.]*$/;
|
|
18
|
+
const REG_SCHEME_CUSTOM = /^(?:ext|web)\+[a-z]+$/;
|
|
19
|
+
const REG_SCRIPT = /(?:java|vb)script/;
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
22
|
* get URL encoded string
|
|
@@ -38,7 +46,7 @@ export const escapeUrlEncodedHtmlChars = ch => {
|
|
|
38
46
|
if (/^%[\dA-F]{2}$/i.test(ch)) {
|
|
39
47
|
ch = ch.toUpperCase();
|
|
40
48
|
} else {
|
|
41
|
-
throw new Error(
|
|
49
|
+
throw new Error(`Invalid URL encoded character: ${ch}`);
|
|
42
50
|
}
|
|
43
51
|
} else {
|
|
44
52
|
throw new TypeError(`Expected String but got ${getType(ch)}.`);
|
|
@@ -63,14 +71,16 @@ export const escapeUrlEncodedHtmlChars = ch => {
|
|
|
63
71
|
};
|
|
64
72
|
|
|
65
73
|
/**
|
|
66
|
-
* parse base64
|
|
74
|
+
* parse base64 encoded data
|
|
67
75
|
*
|
|
68
|
-
* @param {string} data - base64 data
|
|
69
|
-
* @returns {string} - parsed data / base64 data
|
|
76
|
+
* @param {string} data - base64 encoded data
|
|
77
|
+
* @returns {string} - parsed text data / base64 encoded data if binary
|
|
70
78
|
*/
|
|
71
79
|
export const parseBase64 = data => {
|
|
72
80
|
if (!isString(data)) {
|
|
73
81
|
throw new TypeError(`Expected String but got ${getType(data)}.`);
|
|
82
|
+
} else if (!/^[\dA-Za-z+/\-_=]+$/.test(data)) {
|
|
83
|
+
throw new Error(`Invalid base64 data: ${data}`);
|
|
74
84
|
}
|
|
75
85
|
const bin = atob(data);
|
|
76
86
|
const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));
|
|
@@ -84,6 +94,54 @@ export const parseBase64 = data => {
|
|
|
84
94
|
return parsedData;
|
|
85
95
|
};
|
|
86
96
|
|
|
97
|
+
/**
|
|
98
|
+
* parse URL encoded numeric character references in the range 0x00 to 0xFF
|
|
99
|
+
*
|
|
100
|
+
* @param {string} str - string
|
|
101
|
+
* @param {number} nest - nest level
|
|
102
|
+
* @returns {string} - parsed string
|
|
103
|
+
*/
|
|
104
|
+
export const parseUrlEncodedNumCharRef = (str, nest = 0) => {
|
|
105
|
+
if (!isString(str)) {
|
|
106
|
+
throw new TypeError(`Expected String but got ${getType(str)}.`);
|
|
107
|
+
}
|
|
108
|
+
if (!Number.isInteger(nest)) {
|
|
109
|
+
throw new TypeError(`Expected Number but got ${getType(nest)}.`);
|
|
110
|
+
} else if (nest > HEX) {
|
|
111
|
+
throw new Error('Character references nested too deeply.');
|
|
112
|
+
}
|
|
113
|
+
let res = decodeURIComponent(str);
|
|
114
|
+
if (/&#/.test(res)) {
|
|
115
|
+
const textChars = new Set(textCharTable);
|
|
116
|
+
const items = [...res.matchAll(REG_NUM_REF)].reverse();
|
|
117
|
+
for (const item of items) {
|
|
118
|
+
const [numCharRef, value] = item;
|
|
119
|
+
let num;
|
|
120
|
+
if (/^x[\dA-F]+/i.test(value)) {
|
|
121
|
+
num = parseInt(`0${value}`, HEX);
|
|
122
|
+
} else if (/^[\d]+/.test(value)) {
|
|
123
|
+
num = parseInt(value);
|
|
124
|
+
}
|
|
125
|
+
if (Number.isInteger(num)) {
|
|
126
|
+
const { index } = item;
|
|
127
|
+
const [preNum, postNum] = [
|
|
128
|
+
res.substring(0, index),
|
|
129
|
+
res.substring(index + numCharRef.length)
|
|
130
|
+
];
|
|
131
|
+
if (textChars.has(num)) {
|
|
132
|
+
res = `${preNum}${String.fromCharCode(num)}${postNum}`;
|
|
133
|
+
if (/#x?$/.test(preNum) || /^#x?[\d]+/.test(postNum)) {
|
|
134
|
+
res = parseUrlEncodedNumCharRef(res, ++nest);
|
|
135
|
+
}
|
|
136
|
+
} else if (num < HEX * HEX) {
|
|
137
|
+
res = `${preNum}${postNum}`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return res;
|
|
143
|
+
};
|
|
144
|
+
|
|
87
145
|
/**
|
|
88
146
|
* URI schemes
|
|
89
147
|
*
|
|
@@ -131,8 +189,7 @@ export class URISchemes {
|
|
|
131
189
|
add(scheme) {
|
|
132
190
|
if (!isString(scheme)) {
|
|
133
191
|
throw new TypeError(`Expected String but got ${getType(scheme)}.`);
|
|
134
|
-
} else if (
|
|
135
|
-
!/^[a-z][a-z0-9+\-.]*$/.test(scheme)) {
|
|
192
|
+
} else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {
|
|
136
193
|
throw new Error(`Invalid scheme: ${scheme}`);
|
|
137
194
|
}
|
|
138
195
|
this.#schemes.add(scheme);
|
|
@@ -162,7 +219,7 @@ export class URISchemes {
|
|
|
162
219
|
const { protocol } = new URL(uri);
|
|
163
220
|
const scheme = protocol.replace(/:$/, '');
|
|
164
221
|
const schemeParts = scheme.split('+');
|
|
165
|
-
res =
|
|
222
|
+
res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||
|
|
166
223
|
schemeParts.every(s => this.#schemes.has(s));
|
|
167
224
|
} catch (e) {
|
|
168
225
|
res = false;
|
|
@@ -201,23 +258,26 @@ export class URLSanitizer extends URISchemes {
|
|
|
201
258
|
sanitize(url, opt = { allow: [], deny: [] }) {
|
|
202
259
|
if (this.#nest > HEX) {
|
|
203
260
|
this.#nest = 0;
|
|
204
|
-
throw new Error('
|
|
261
|
+
throw new Error('Data URLs nested too deeply.');
|
|
205
262
|
}
|
|
206
263
|
let sanitizedUrl;
|
|
207
264
|
if (super.isURI(url)) {
|
|
208
265
|
const { allow, deny } = opt ?? {};
|
|
209
|
-
const { href, pathname, protocol } = new URL(url);
|
|
266
|
+
const { hash, href, pathname, protocol, search } = new URL(url);
|
|
210
267
|
const scheme = protocol.replace(/:$/, '');
|
|
211
268
|
const schemeParts = scheme.split('+');
|
|
212
|
-
const schemeMap = new Map([
|
|
269
|
+
const schemeMap = new Map([
|
|
270
|
+
['data', false],
|
|
271
|
+
['file', false],
|
|
272
|
+
['javascrpt', false],
|
|
273
|
+
['vbscript', false]
|
|
274
|
+
]);
|
|
213
275
|
if (Array.isArray(allow) && allow.length) {
|
|
214
276
|
const items = Object.values(allow);
|
|
215
277
|
for (let item of items) {
|
|
216
278
|
if (isString(item)) {
|
|
217
279
|
item = item.trim();
|
|
218
|
-
if (
|
|
219
|
-
schemeMap.set(item, false);
|
|
220
|
-
} else if (item) {
|
|
280
|
+
if (!REG_SCRIPT.test(item)) {
|
|
221
281
|
schemeMap.set(item, true);
|
|
222
282
|
}
|
|
223
283
|
}
|
|
@@ -244,43 +304,53 @@ export class URLSanitizer extends URISchemes {
|
|
|
244
304
|
if (bool) {
|
|
245
305
|
const [amp, lt, gt, quot, apos] =
|
|
246
306
|
['&', '<', '>', '"', "'"].map(getUrlEncodedString);
|
|
247
|
-
const regChars = /[<>"']/g;
|
|
248
307
|
const regAmp = new RegExp(amp, 'g');
|
|
249
308
|
const regEncodedChars =
|
|
250
309
|
new RegExp(`(${lt}|${gt}|${quot}|${apos})`, 'g');
|
|
251
310
|
let escapeHtml;
|
|
252
311
|
let urlToSanitize = href;
|
|
253
312
|
if (schemeParts.includes('data')) {
|
|
254
|
-
const [header,
|
|
313
|
+
const [header, ...body] = pathname.split(',');
|
|
314
|
+
const data = `${body.join(',')}${search}${hash}`;
|
|
255
315
|
const mediaType = header.split(';');
|
|
256
|
-
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
316
|
+
let parsedData = data;
|
|
317
|
+
if (mediaType[mediaType.length - 1] === 'base64') {
|
|
318
|
+
mediaType.pop();
|
|
319
|
+
parsedData = parseBase64(data);
|
|
320
|
+
} else {
|
|
321
|
+
try {
|
|
322
|
+
const decodedData = parseUrlEncodedNumCharRef(parsedData);
|
|
323
|
+
const { protocol: dataScheme } = new URL(decodedData.trim());
|
|
324
|
+
const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');
|
|
325
|
+
if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {
|
|
326
|
+
urlToSanitize = '';
|
|
327
|
+
}
|
|
328
|
+
} catch (e) {
|
|
329
|
+
// fall through
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const containsDataUrl = REG_DATA_URL_HEADER.test(parsedData);
|
|
333
|
+
if (parsedData !== data || containsDataUrl) {
|
|
334
|
+
if (containsDataUrl) {
|
|
335
|
+
const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);
|
|
336
|
+
const items = [...matchedDataUrls].reverse();
|
|
337
|
+
for (const item of items) {
|
|
338
|
+
let [dataUrl] = item;
|
|
339
|
+
if (REG_DATA_URL_BASE64.test(dataUrl)) {
|
|
340
|
+
[dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);
|
|
341
|
+
}
|
|
342
|
+
this.#nest++;
|
|
343
|
+
this.#recurse.add(dataUrl);
|
|
344
|
+
const parsedDataUrl = this.sanitize(dataUrl, {
|
|
345
|
+
allow: ['data']
|
|
346
|
+
});
|
|
347
|
+
if (parsedDataUrl) {
|
|
348
|
+
const { index } = item;
|
|
349
|
+
const [preDataUrl, postDataUrl] = [
|
|
350
|
+
parsedData.substring(0, index),
|
|
351
|
+
parsedData.substring(index + dataUrl.length)
|
|
352
|
+
];
|
|
353
|
+
parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
|
|
284
354
|
}
|
|
285
355
|
}
|
|
286
356
|
if (this.#recurse.has(url)) {
|
|
@@ -288,10 +358,12 @@ export class URLSanitizer extends URISchemes {
|
|
|
288
358
|
} else {
|
|
289
359
|
escapeHtml = true;
|
|
290
360
|
}
|
|
291
|
-
|
|
361
|
+
} else if (this.#recurse.has(url)) {
|
|
362
|
+
this.#recurse.delete(url);
|
|
292
363
|
} else {
|
|
293
364
|
escapeHtml = true;
|
|
294
365
|
}
|
|
366
|
+
urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;
|
|
295
367
|
} else if (this.#recurse.has(url)) {
|
|
296
368
|
this.#recurse.delete(url);
|
|
297
369
|
} else {
|
|
@@ -300,11 +372,16 @@ export class URLSanitizer extends URISchemes {
|
|
|
300
372
|
} else {
|
|
301
373
|
escapeHtml = true;
|
|
302
374
|
}
|
|
303
|
-
|
|
304
|
-
.replace(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
sanitizedUrl
|
|
375
|
+
if (urlToSanitize) {
|
|
376
|
+
sanitizedUrl = urlToSanitize.replace(REG_CHARS, getUrlEncodedString)
|
|
377
|
+
.replace(regAmp, escapeUrlEncodedHtmlChars);
|
|
378
|
+
if (escapeHtml) {
|
|
379
|
+
sanitizedUrl =
|
|
380
|
+
sanitizedUrl.replace(regEncodedChars, escapeUrlEncodedHtmlChars);
|
|
381
|
+
this.#nest = 0;
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
sanitizedUrl = urlToSanitize;
|
|
308
385
|
this.#nest = 0;
|
|
309
386
|
}
|
|
310
387
|
}
|