siteversion 0.0.1-security → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of siteversion might be problematic. Click here for more details.
- package/index.js +56 -0
- package/package.json +14 -3
- package/proof/node_modules/dellingr/index.js +64 -0
- package/proof/node_modules/dellingr/package.json +41 -0
- package/proof/node_modules/dellingr/proof/package-lock.json +49 -0
- package/proof/node_modules/dellingr/proof/package.json +15 -0
- package/proof/node_modules/dotenv/CHANGELOG.md +347 -0
- package/proof/node_modules/dotenv/LICENSE +23 -0
- package/proof/node_modules/dotenv/README.md +406 -0
- package/proof/node_modules/dotenv/config.d.ts +1 -0
- package/proof/node_modules/dotenv/config.js +9 -0
- package/proof/node_modules/dotenv/lib/cli-options.js +11 -0
- package/proof/node_modules/dotenv/lib/env-options.js +20 -0
- package/proof/node_modules/dotenv/lib/main.d.ts +73 -0
- package/proof/node_modules/dotenv/lib/main.js +109 -0
- package/proof/node_modules/dotenv/package.json +86 -0
- package/proof/node_modules/node-fetch/LICENSE.md +22 -0
- package/proof/node_modules/node-fetch/README.md +590 -0
- package/proof/node_modules/node-fetch/browser.js +25 -0
- package/proof/node_modules/node-fetch/lib/index.es.js +1688 -0
- package/proof/node_modules/node-fetch/lib/index.js +1697 -0
- package/proof/node_modules/node-fetch/lib/index.mjs +1686 -0
- package/proof/node_modules/node-fetch/package.json +106 -0
- package/proof/node_modules/tr46/index.js +193 -0
- package/proof/node_modules/tr46/lib/.gitkeep +0 -0
- package/proof/node_modules/tr46/lib/mappingTable.json +1 -0
- package/proof/node_modules/tr46/package.json +62 -0
- package/proof/node_modules/webidl-conversions/LICENSE.md +12 -0
- package/proof/node_modules/webidl-conversions/README.md +53 -0
- package/proof/node_modules/webidl-conversions/lib/index.js +189 -0
- package/proof/node_modules/webidl-conversions/package.json +62 -0
- package/proof/node_modules/whatwg-url/LICENSE.txt +21 -0
- package/proof/node_modules/whatwg-url/README.md +67 -0
- package/proof/node_modules/whatwg-url/lib/URL-impl.js +200 -0
- package/proof/node_modules/whatwg-url/lib/URL.js +196 -0
- package/proof/node_modules/whatwg-url/lib/public-api.js +11 -0
- package/proof/node_modules/whatwg-url/lib/url-state-machine.js +1297 -0
- package/proof/node_modules/whatwg-url/lib/utils.js +20 -0
- package/proof/node_modules/whatwg-url/package.json +70 -0
- package/proof/package-lock.json +49 -0
- package/proof/package.json +15 -0
- package/README.md +0 -5
@@ -0,0 +1,1297 @@
|
|
1
|
+
"use strict";
|
2
|
+
const punycode = require("punycode");
|
3
|
+
const tr46 = require("tr46");
|
4
|
+
|
5
|
+
const specialSchemes = {
|
6
|
+
ftp: 21,
|
7
|
+
file: null,
|
8
|
+
gopher: 70,
|
9
|
+
http: 80,
|
10
|
+
https: 443,
|
11
|
+
ws: 80,
|
12
|
+
wss: 443
|
13
|
+
};
|
14
|
+
|
15
|
+
const failure = Symbol("failure");
|
16
|
+
|
17
|
+
function countSymbols(str) {
|
18
|
+
return punycode.ucs2.decode(str).length;
|
19
|
+
}
|
20
|
+
|
21
|
+
function at(input, idx) {
|
22
|
+
const c = input[idx];
|
23
|
+
return isNaN(c) ? undefined : String.fromCodePoint(c);
|
24
|
+
}
|
25
|
+
|
26
|
+
function isASCIIDigit(c) {
|
27
|
+
return c >= 0x30 && c <= 0x39;
|
28
|
+
}
|
29
|
+
|
30
|
+
function isASCIIAlpha(c) {
|
31
|
+
return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
|
32
|
+
}
|
33
|
+
|
34
|
+
function isASCIIAlphanumeric(c) {
|
35
|
+
return isASCIIAlpha(c) || isASCIIDigit(c);
|
36
|
+
}
|
37
|
+
|
38
|
+
function isASCIIHex(c) {
|
39
|
+
return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
|
40
|
+
}
|
41
|
+
|
42
|
+
function isSingleDot(buffer) {
|
43
|
+
return buffer === "." || buffer.toLowerCase() === "%2e";
|
44
|
+
}
|
45
|
+
|
46
|
+
function isDoubleDot(buffer) {
|
47
|
+
buffer = buffer.toLowerCase();
|
48
|
+
return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e";
|
49
|
+
}
|
50
|
+
|
51
|
+
function isWindowsDriveLetterCodePoints(cp1, cp2) {
|
52
|
+
return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124);
|
53
|
+
}
|
54
|
+
|
55
|
+
function isWindowsDriveLetterString(string) {
|
56
|
+
return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|");
|
57
|
+
}
|
58
|
+
|
59
|
+
function isNormalizedWindowsDriveLetterString(string) {
|
60
|
+
return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":";
|
61
|
+
}
|
62
|
+
|
63
|
+
function containsForbiddenHostCodePoint(string) {
|
64
|
+
return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1;
|
65
|
+
}
|
66
|
+
|
67
|
+
function containsForbiddenHostCodePointExcludingPercent(string) {
|
68
|
+
return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1;
|
69
|
+
}
|
70
|
+
|
71
|
+
function isSpecialScheme(scheme) {
|
72
|
+
return specialSchemes[scheme] !== undefined;
|
73
|
+
}
|
74
|
+
|
75
|
+
function isSpecial(url) {
|
76
|
+
return isSpecialScheme(url.scheme);
|
77
|
+
}
|
78
|
+
|
79
|
+
function defaultPort(scheme) {
|
80
|
+
return specialSchemes[scheme];
|
81
|
+
}
|
82
|
+
|
83
|
+
function percentEncode(c) {
|
84
|
+
let hex = c.toString(16).toUpperCase();
|
85
|
+
if (hex.length === 1) {
|
86
|
+
hex = "0" + hex;
|
87
|
+
}
|
88
|
+
|
89
|
+
return "%" + hex;
|
90
|
+
}
|
91
|
+
|
92
|
+
function utf8PercentEncode(c) {
|
93
|
+
const buf = new Buffer(c);
|
94
|
+
|
95
|
+
let str = "";
|
96
|
+
|
97
|
+
for (let i = 0; i < buf.length; ++i) {
|
98
|
+
str += percentEncode(buf[i]);
|
99
|
+
}
|
100
|
+
|
101
|
+
return str;
|
102
|
+
}
|
103
|
+
|
104
|
+
function utf8PercentDecode(str) {
|
105
|
+
const input = new Buffer(str);
|
106
|
+
const output = [];
|
107
|
+
for (let i = 0; i < input.length; ++i) {
|
108
|
+
if (input[i] !== 37) {
|
109
|
+
output.push(input[i]);
|
110
|
+
} else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) {
|
111
|
+
output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16));
|
112
|
+
i += 2;
|
113
|
+
} else {
|
114
|
+
output.push(input[i]);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
return new Buffer(output).toString();
|
118
|
+
}
|
119
|
+
|
120
|
+
function isC0ControlPercentEncode(c) {
|
121
|
+
return c <= 0x1F || c > 0x7E;
|
122
|
+
}
|
123
|
+
|
124
|
+
const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]);
|
125
|
+
function isPathPercentEncode(c) {
|
126
|
+
return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c);
|
127
|
+
}
|
128
|
+
|
129
|
+
const extraUserinfoPercentEncodeSet =
|
130
|
+
new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]);
|
131
|
+
function isUserinfoPercentEncode(c) {
|
132
|
+
return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
|
133
|
+
}
|
134
|
+
|
135
|
+
function percentEncodeChar(c, encodeSetPredicate) {
|
136
|
+
const cStr = String.fromCodePoint(c);
|
137
|
+
|
138
|
+
if (encodeSetPredicate(c)) {
|
139
|
+
return utf8PercentEncode(cStr);
|
140
|
+
}
|
141
|
+
|
142
|
+
return cStr;
|
143
|
+
}
|
144
|
+
|
145
|
+
function parseIPv4Number(input) {
|
146
|
+
let R = 10;
|
147
|
+
|
148
|
+
if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") {
|
149
|
+
input = input.substring(2);
|
150
|
+
R = 16;
|
151
|
+
} else if (input.length >= 2 && input.charAt(0) === "0") {
|
152
|
+
input = input.substring(1);
|
153
|
+
R = 8;
|
154
|
+
}
|
155
|
+
|
156
|
+
if (input === "") {
|
157
|
+
return 0;
|
158
|
+
}
|
159
|
+
|
160
|
+
const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/);
|
161
|
+
if (regex.test(input)) {
|
162
|
+
return failure;
|
163
|
+
}
|
164
|
+
|
165
|
+
return parseInt(input, R);
|
166
|
+
}
|
167
|
+
|
168
|
+
function parseIPv4(input) {
|
169
|
+
const parts = input.split(".");
|
170
|
+
if (parts[parts.length - 1] === "") {
|
171
|
+
if (parts.length > 1) {
|
172
|
+
parts.pop();
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
if (parts.length > 4) {
|
177
|
+
return input;
|
178
|
+
}
|
179
|
+
|
180
|
+
const numbers = [];
|
181
|
+
for (const part of parts) {
|
182
|
+
if (part === "") {
|
183
|
+
return input;
|
184
|
+
}
|
185
|
+
const n = parseIPv4Number(part);
|
186
|
+
if (n === failure) {
|
187
|
+
return input;
|
188
|
+
}
|
189
|
+
|
190
|
+
numbers.push(n);
|
191
|
+
}
|
192
|
+
|
193
|
+
for (let i = 0; i < numbers.length - 1; ++i) {
|
194
|
+
if (numbers[i] > 255) {
|
195
|
+
return failure;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) {
|
199
|
+
return failure;
|
200
|
+
}
|
201
|
+
|
202
|
+
let ipv4 = numbers.pop();
|
203
|
+
let counter = 0;
|
204
|
+
|
205
|
+
for (const n of numbers) {
|
206
|
+
ipv4 += n * Math.pow(256, 3 - counter);
|
207
|
+
++counter;
|
208
|
+
}
|
209
|
+
|
210
|
+
return ipv4;
|
211
|
+
}
|
212
|
+
|
213
|
+
function serializeIPv4(address) {
|
214
|
+
let output = "";
|
215
|
+
let n = address;
|
216
|
+
|
217
|
+
for (let i = 1; i <= 4; ++i) {
|
218
|
+
output = String(n % 256) + output;
|
219
|
+
if (i !== 4) {
|
220
|
+
output = "." + output;
|
221
|
+
}
|
222
|
+
n = Math.floor(n / 256);
|
223
|
+
}
|
224
|
+
|
225
|
+
return output;
|
226
|
+
}
|
227
|
+
|
228
|
+
function parseIPv6(input) {
|
229
|
+
const address = [0, 0, 0, 0, 0, 0, 0, 0];
|
230
|
+
let pieceIndex = 0;
|
231
|
+
let compress = null;
|
232
|
+
let pointer = 0;
|
233
|
+
|
234
|
+
input = punycode.ucs2.decode(input);
|
235
|
+
|
236
|
+
if (input[pointer] === 58) {
|
237
|
+
if (input[pointer + 1] !== 58) {
|
238
|
+
return failure;
|
239
|
+
}
|
240
|
+
|
241
|
+
pointer += 2;
|
242
|
+
++pieceIndex;
|
243
|
+
compress = pieceIndex;
|
244
|
+
}
|
245
|
+
|
246
|
+
while (pointer < input.length) {
|
247
|
+
if (pieceIndex === 8) {
|
248
|
+
return failure;
|
249
|
+
}
|
250
|
+
|
251
|
+
if (input[pointer] === 58) {
|
252
|
+
if (compress !== null) {
|
253
|
+
return failure;
|
254
|
+
}
|
255
|
+
++pointer;
|
256
|
+
++pieceIndex;
|
257
|
+
compress = pieceIndex;
|
258
|
+
continue;
|
259
|
+
}
|
260
|
+
|
261
|
+
let value = 0;
|
262
|
+
let length = 0;
|
263
|
+
|
264
|
+
while (length < 4 && isASCIIHex(input[pointer])) {
|
265
|
+
value = value * 0x10 + parseInt(at(input, pointer), 16);
|
266
|
+
++pointer;
|
267
|
+
++length;
|
268
|
+
}
|
269
|
+
|
270
|
+
if (input[pointer] === 46) {
|
271
|
+
if (length === 0) {
|
272
|
+
return failure;
|
273
|
+
}
|
274
|
+
|
275
|
+
pointer -= length;
|
276
|
+
|
277
|
+
if (pieceIndex > 6) {
|
278
|
+
return failure;
|
279
|
+
}
|
280
|
+
|
281
|
+
let numbersSeen = 0;
|
282
|
+
|
283
|
+
while (input[pointer] !== undefined) {
|
284
|
+
let ipv4Piece = null;
|
285
|
+
|
286
|
+
if (numbersSeen > 0) {
|
287
|
+
if (input[pointer] === 46 && numbersSeen < 4) {
|
288
|
+
++pointer;
|
289
|
+
} else {
|
290
|
+
return failure;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
if (!isASCIIDigit(input[pointer])) {
|
295
|
+
return failure;
|
296
|
+
}
|
297
|
+
|
298
|
+
while (isASCIIDigit(input[pointer])) {
|
299
|
+
const number = parseInt(at(input, pointer));
|
300
|
+
if (ipv4Piece === null) {
|
301
|
+
ipv4Piece = number;
|
302
|
+
} else if (ipv4Piece === 0) {
|
303
|
+
return failure;
|
304
|
+
} else {
|
305
|
+
ipv4Piece = ipv4Piece * 10 + number;
|
306
|
+
}
|
307
|
+
if (ipv4Piece > 255) {
|
308
|
+
return failure;
|
309
|
+
}
|
310
|
+
++pointer;
|
311
|
+
}
|
312
|
+
|
313
|
+
address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece;
|
314
|
+
|
315
|
+
++numbersSeen;
|
316
|
+
|
317
|
+
if (numbersSeen === 2 || numbersSeen === 4) {
|
318
|
+
++pieceIndex;
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
if (numbersSeen !== 4) {
|
323
|
+
return failure;
|
324
|
+
}
|
325
|
+
|
326
|
+
break;
|
327
|
+
} else if (input[pointer] === 58) {
|
328
|
+
++pointer;
|
329
|
+
if (input[pointer] === undefined) {
|
330
|
+
return failure;
|
331
|
+
}
|
332
|
+
} else if (input[pointer] !== undefined) {
|
333
|
+
return failure;
|
334
|
+
}
|
335
|
+
|
336
|
+
address[pieceIndex] = value;
|
337
|
+
++pieceIndex;
|
338
|
+
}
|
339
|
+
|
340
|
+
if (compress !== null) {
|
341
|
+
let swaps = pieceIndex - compress;
|
342
|
+
pieceIndex = 7;
|
343
|
+
while (pieceIndex !== 0 && swaps > 0) {
|
344
|
+
const temp = address[compress + swaps - 1];
|
345
|
+
address[compress + swaps - 1] = address[pieceIndex];
|
346
|
+
address[pieceIndex] = temp;
|
347
|
+
--pieceIndex;
|
348
|
+
--swaps;
|
349
|
+
}
|
350
|
+
} else if (compress === null && pieceIndex !== 8) {
|
351
|
+
return failure;
|
352
|
+
}
|
353
|
+
|
354
|
+
return address;
|
355
|
+
}
|
356
|
+
|
357
|
+
function serializeIPv6(address) {
|
358
|
+
let output = "";
|
359
|
+
const seqResult = findLongestZeroSequence(address);
|
360
|
+
const compress = seqResult.idx;
|
361
|
+
let ignore0 = false;
|
362
|
+
|
363
|
+
for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) {
|
364
|
+
if (ignore0 && address[pieceIndex] === 0) {
|
365
|
+
continue;
|
366
|
+
} else if (ignore0) {
|
367
|
+
ignore0 = false;
|
368
|
+
}
|
369
|
+
|
370
|
+
if (compress === pieceIndex) {
|
371
|
+
const separator = pieceIndex === 0 ? "::" : ":";
|
372
|
+
output += separator;
|
373
|
+
ignore0 = true;
|
374
|
+
continue;
|
375
|
+
}
|
376
|
+
|
377
|
+
output += address[pieceIndex].toString(16);
|
378
|
+
|
379
|
+
if (pieceIndex !== 7) {
|
380
|
+
output += ":";
|
381
|
+
}
|
382
|
+
}
|
383
|
+
|
384
|
+
return output;
|
385
|
+
}
|
386
|
+
|
387
|
+
function parseHost(input, isSpecialArg) {
|
388
|
+
if (input[0] === "[") {
|
389
|
+
if (input[input.length - 1] !== "]") {
|
390
|
+
return failure;
|
391
|
+
}
|
392
|
+
|
393
|
+
return parseIPv6(input.substring(1, input.length - 1));
|
394
|
+
}
|
395
|
+
|
396
|
+
if (!isSpecialArg) {
|
397
|
+
return parseOpaqueHost(input);
|
398
|
+
}
|
399
|
+
|
400
|
+
const domain = utf8PercentDecode(input);
|
401
|
+
const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false);
|
402
|
+
if (asciiDomain === null) {
|
403
|
+
return failure;
|
404
|
+
}
|
405
|
+
|
406
|
+
if (containsForbiddenHostCodePoint(asciiDomain)) {
|
407
|
+
return failure;
|
408
|
+
}
|
409
|
+
|
410
|
+
const ipv4Host = parseIPv4(asciiDomain);
|
411
|
+
if (typeof ipv4Host === "number" || ipv4Host === failure) {
|
412
|
+
return ipv4Host;
|
413
|
+
}
|
414
|
+
|
415
|
+
return asciiDomain;
|
416
|
+
}
|
417
|
+
|
418
|
+
function parseOpaqueHost(input) {
|
419
|
+
if (containsForbiddenHostCodePointExcludingPercent(input)) {
|
420
|
+
return failure;
|
421
|
+
}
|
422
|
+
|
423
|
+
let output = "";
|
424
|
+
const decoded = punycode.ucs2.decode(input);
|
425
|
+
for (let i = 0; i < decoded.length; ++i) {
|
426
|
+
output += percentEncodeChar(decoded[i], isC0ControlPercentEncode);
|
427
|
+
}
|
428
|
+
return output;
|
429
|
+
}
|
430
|
+
|
431
|
+
function findLongestZeroSequence(arr) {
|
432
|
+
let maxIdx = null;
|
433
|
+
let maxLen = 1; // only find elements > 1
|
434
|
+
let currStart = null;
|
435
|
+
let currLen = 0;
|
436
|
+
|
437
|
+
for (let i = 0; i < arr.length; ++i) {
|
438
|
+
if (arr[i] !== 0) {
|
439
|
+
if (currLen > maxLen) {
|
440
|
+
maxIdx = currStart;
|
441
|
+
maxLen = currLen;
|
442
|
+
}
|
443
|
+
|
444
|
+
currStart = null;
|
445
|
+
currLen = 0;
|
446
|
+
} else {
|
447
|
+
if (currStart === null) {
|
448
|
+
currStart = i;
|
449
|
+
}
|
450
|
+
++currLen;
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
// if trailing zeros
|
455
|
+
if (currLen > maxLen) {
|
456
|
+
maxIdx = currStart;
|
457
|
+
maxLen = currLen;
|
458
|
+
}
|
459
|
+
|
460
|
+
return {
|
461
|
+
idx: maxIdx,
|
462
|
+
len: maxLen
|
463
|
+
};
|
464
|
+
}
|
465
|
+
|
466
|
+
function serializeHost(host) {
|
467
|
+
if (typeof host === "number") {
|
468
|
+
return serializeIPv4(host);
|
469
|
+
}
|
470
|
+
|
471
|
+
// IPv6 serializer
|
472
|
+
if (host instanceof Array) {
|
473
|
+
return "[" + serializeIPv6(host) + "]";
|
474
|
+
}
|
475
|
+
|
476
|
+
return host;
|
477
|
+
}
|
478
|
+
|
479
|
+
function trimControlChars(url) {
|
480
|
+
return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, "");
|
481
|
+
}
|
482
|
+
|
483
|
+
function trimTabAndNewline(url) {
|
484
|
+
return url.replace(/\u0009|\u000A|\u000D/g, "");
|
485
|
+
}
|
486
|
+
|
487
|
+
function shortenPath(url) {
|
488
|
+
const path = url.path;
|
489
|
+
if (path.length === 0) {
|
490
|
+
return;
|
491
|
+
}
|
492
|
+
if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
|
493
|
+
return;
|
494
|
+
}
|
495
|
+
|
496
|
+
path.pop();
|
497
|
+
}
|
498
|
+
|
499
|
+
function includesCredentials(url) {
|
500
|
+
return url.username !== "" || url.password !== "";
|
501
|
+
}
|
502
|
+
|
503
|
+
function cannotHaveAUsernamePasswordPort(url) {
|
504
|
+
return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file";
|
505
|
+
}
|
506
|
+
|
507
|
+
function isNormalizedWindowsDriveLetter(string) {
|
508
|
+
return /^[A-Za-z]:$/.test(string);
|
509
|
+
}
|
510
|
+
|
511
|
+
function URLStateMachine(input, base, encodingOverride, url, stateOverride) {
|
512
|
+
this.pointer = 0;
|
513
|
+
this.input = input;
|
514
|
+
this.base = base || null;
|
515
|
+
this.encodingOverride = encodingOverride || "utf-8";
|
516
|
+
this.stateOverride = stateOverride;
|
517
|
+
this.url = url;
|
518
|
+
this.failure = false;
|
519
|
+
this.parseError = false;
|
520
|
+
|
521
|
+
if (!this.url) {
|
522
|
+
this.url = {
|
523
|
+
scheme: "",
|
524
|
+
username: "",
|
525
|
+
password: "",
|
526
|
+
host: null,
|
527
|
+
port: null,
|
528
|
+
path: [],
|
529
|
+
query: null,
|
530
|
+
fragment: null,
|
531
|
+
|
532
|
+
cannotBeABaseURL: false
|
533
|
+
};
|
534
|
+
|
535
|
+
const res = trimControlChars(this.input);
|
536
|
+
if (res !== this.input) {
|
537
|
+
this.parseError = true;
|
538
|
+
}
|
539
|
+
this.input = res;
|
540
|
+
}
|
541
|
+
|
542
|
+
const res = trimTabAndNewline(this.input);
|
543
|
+
if (res !== this.input) {
|
544
|
+
this.parseError = true;
|
545
|
+
}
|
546
|
+
this.input = res;
|
547
|
+
|
548
|
+
this.state = stateOverride || "scheme start";
|
549
|
+
|
550
|
+
this.buffer = "";
|
551
|
+
this.atFlag = false;
|
552
|
+
this.arrFlag = false;
|
553
|
+
this.passwordTokenSeenFlag = false;
|
554
|
+
|
555
|
+
this.input = punycode.ucs2.decode(this.input);
|
556
|
+
|
557
|
+
for (; this.pointer <= this.input.length; ++this.pointer) {
|
558
|
+
const c = this.input[this.pointer];
|
559
|
+
const cStr = isNaN(c) ? undefined : String.fromCodePoint(c);
|
560
|
+
|
561
|
+
// exec state machine
|
562
|
+
const ret = this["parse " + this.state](c, cStr);
|
563
|
+
if (!ret) {
|
564
|
+
break; // terminate algorithm
|
565
|
+
} else if (ret === failure) {
|
566
|
+
this.failure = true;
|
567
|
+
break;
|
568
|
+
}
|
569
|
+
}
|
570
|
+
}
|
571
|
+
|
572
|
+
URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) {
|
573
|
+
if (isASCIIAlpha(c)) {
|
574
|
+
this.buffer += cStr.toLowerCase();
|
575
|
+
this.state = "scheme";
|
576
|
+
} else if (!this.stateOverride) {
|
577
|
+
this.state = "no scheme";
|
578
|
+
--this.pointer;
|
579
|
+
} else {
|
580
|
+
this.parseError = true;
|
581
|
+
return failure;
|
582
|
+
}
|
583
|
+
|
584
|
+
return true;
|
585
|
+
};
|
586
|
+
|
587
|
+
URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) {
|
588
|
+
if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) {
|
589
|
+
this.buffer += cStr.toLowerCase();
|
590
|
+
} else if (c === 58) {
|
591
|
+
if (this.stateOverride) {
|
592
|
+
if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) {
|
593
|
+
return false;
|
594
|
+
}
|
595
|
+
|
596
|
+
if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) {
|
597
|
+
return false;
|
598
|
+
}
|
599
|
+
|
600
|
+
if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") {
|
601
|
+
return false;
|
602
|
+
}
|
603
|
+
|
604
|
+
if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) {
|
605
|
+
return false;
|
606
|
+
}
|
607
|
+
}
|
608
|
+
this.url.scheme = this.buffer;
|
609
|
+
this.buffer = "";
|
610
|
+
if (this.stateOverride) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
if (this.url.scheme === "file") {
|
614
|
+
if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) {
|
615
|
+
this.parseError = true;
|
616
|
+
}
|
617
|
+
this.state = "file";
|
618
|
+
} else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) {
|
619
|
+
this.state = "special relative or authority";
|
620
|
+
} else if (isSpecial(this.url)) {
|
621
|
+
this.state = "special authority slashes";
|
622
|
+
} else if (this.input[this.pointer + 1] === 47) {
|
623
|
+
this.state = "path or authority";
|
624
|
+
++this.pointer;
|
625
|
+
} else {
|
626
|
+
this.url.cannotBeABaseURL = true;
|
627
|
+
this.url.path.push("");
|
628
|
+
this.state = "cannot-be-a-base-URL path";
|
629
|
+
}
|
630
|
+
} else if (!this.stateOverride) {
|
631
|
+
this.buffer = "";
|
632
|
+
this.state = "no scheme";
|
633
|
+
this.pointer = -1;
|
634
|
+
} else {
|
635
|
+
this.parseError = true;
|
636
|
+
return failure;
|
637
|
+
}
|
638
|
+
|
639
|
+
return true;
|
640
|
+
};
|
641
|
+
|
642
|
+
URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) {
|
643
|
+
if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) {
|
644
|
+
return failure;
|
645
|
+
} else if (this.base.cannotBeABaseURL && c === 35) {
|
646
|
+
this.url.scheme = this.base.scheme;
|
647
|
+
this.url.path = this.base.path.slice();
|
648
|
+
this.url.query = this.base.query;
|
649
|
+
this.url.fragment = "";
|
650
|
+
this.url.cannotBeABaseURL = true;
|
651
|
+
this.state = "fragment";
|
652
|
+
} else if (this.base.scheme === "file") {
|
653
|
+
this.state = "file";
|
654
|
+
--this.pointer;
|
655
|
+
} else {
|
656
|
+
this.state = "relative";
|
657
|
+
--this.pointer;
|
658
|
+
}
|
659
|
+
|
660
|
+
return true;
|
661
|
+
};
|
662
|
+
|
663
|
+
URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) {
|
664
|
+
if (c === 47 && this.input[this.pointer + 1] === 47) {
|
665
|
+
this.state = "special authority ignore slashes";
|
666
|
+
++this.pointer;
|
667
|
+
} else {
|
668
|
+
this.parseError = true;
|
669
|
+
this.state = "relative";
|
670
|
+
--this.pointer;
|
671
|
+
}
|
672
|
+
|
673
|
+
return true;
|
674
|
+
};
|
675
|
+
|
676
|
+
URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) {
|
677
|
+
if (c === 47) {
|
678
|
+
this.state = "authority";
|
679
|
+
} else {
|
680
|
+
this.state = "path";
|
681
|
+
--this.pointer;
|
682
|
+
}
|
683
|
+
|
684
|
+
return true;
|
685
|
+
};
|
686
|
+
|
687
|
+
URLStateMachine.prototype["parse relative"] = function parseRelative(c) {
|
688
|
+
this.url.scheme = this.base.scheme;
|
689
|
+
if (isNaN(c)) {
|
690
|
+
this.url.username = this.base.username;
|
691
|
+
this.url.password = this.base.password;
|
692
|
+
this.url.host = this.base.host;
|
693
|
+
this.url.port = this.base.port;
|
694
|
+
this.url.path = this.base.path.slice();
|
695
|
+
this.url.query = this.base.query;
|
696
|
+
} else if (c === 47) {
|
697
|
+
this.state = "relative slash";
|
698
|
+
} else if (c === 63) {
|
699
|
+
this.url.username = this.base.username;
|
700
|
+
this.url.password = this.base.password;
|
701
|
+
this.url.host = this.base.host;
|
702
|
+
this.url.port = this.base.port;
|
703
|
+
this.url.path = this.base.path.slice();
|
704
|
+
this.url.query = "";
|
705
|
+
this.state = "query";
|
706
|
+
} else if (c === 35) {
|
707
|
+
this.url.username = this.base.username;
|
708
|
+
this.url.password = this.base.password;
|
709
|
+
this.url.host = this.base.host;
|
710
|
+
this.url.port = this.base.port;
|
711
|
+
this.url.path = this.base.path.slice();
|
712
|
+
this.url.query = this.base.query;
|
713
|
+
this.url.fragment = "";
|
714
|
+
this.state = "fragment";
|
715
|
+
} else if (isSpecial(this.url) && c === 92) {
|
716
|
+
this.parseError = true;
|
717
|
+
this.state = "relative slash";
|
718
|
+
} else {
|
719
|
+
this.url.username = this.base.username;
|
720
|
+
this.url.password = this.base.password;
|
721
|
+
this.url.host = this.base.host;
|
722
|
+
this.url.port = this.base.port;
|
723
|
+
this.url.path = this.base.path.slice(0, this.base.path.length - 1);
|
724
|
+
|
725
|
+
this.state = "path";
|
726
|
+
--this.pointer;
|
727
|
+
}
|
728
|
+
|
729
|
+
return true;
|
730
|
+
};
|
731
|
+
|
732
|
+
URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) {
|
733
|
+
if (isSpecial(this.url) && (c === 47 || c === 92)) {
|
734
|
+
if (c === 92) {
|
735
|
+
this.parseError = true;
|
736
|
+
}
|
737
|
+
this.state = "special authority ignore slashes";
|
738
|
+
} else if (c === 47) {
|
739
|
+
this.state = "authority";
|
740
|
+
} else {
|
741
|
+
this.url.username = this.base.username;
|
742
|
+
this.url.password = this.base.password;
|
743
|
+
this.url.host = this.base.host;
|
744
|
+
this.url.port = this.base.port;
|
745
|
+
this.state = "path";
|
746
|
+
--this.pointer;
|
747
|
+
}
|
748
|
+
|
749
|
+
return true;
|
750
|
+
};
|
751
|
+
|
752
|
+
URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) {
|
753
|
+
if (c === 47 && this.input[this.pointer + 1] === 47) {
|
754
|
+
this.state = "special authority ignore slashes";
|
755
|
+
++this.pointer;
|
756
|
+
} else {
|
757
|
+
this.parseError = true;
|
758
|
+
this.state = "special authority ignore slashes";
|
759
|
+
--this.pointer;
|
760
|
+
}
|
761
|
+
|
762
|
+
return true;
|
763
|
+
};
|
764
|
+
|
765
|
+
URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) {
|
766
|
+
if (c !== 47 && c !== 92) {
|
767
|
+
this.state = "authority";
|
768
|
+
--this.pointer;
|
769
|
+
} else {
|
770
|
+
this.parseError = true;
|
771
|
+
}
|
772
|
+
|
773
|
+
return true;
|
774
|
+
};
|
775
|
+
|
776
|
+
URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) {
|
777
|
+
if (c === 64) {
|
778
|
+
this.parseError = true;
|
779
|
+
if (this.atFlag) {
|
780
|
+
this.buffer = "%40" + this.buffer;
|
781
|
+
}
|
782
|
+
this.atFlag = true;
|
783
|
+
|
784
|
+
// careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars
|
785
|
+
const len = countSymbols(this.buffer);
|
786
|
+
for (let pointer = 0; pointer < len; ++pointer) {
|
787
|
+
const codePoint = this.buffer.codePointAt(pointer);
|
788
|
+
|
789
|
+
if (codePoint === 58 && !this.passwordTokenSeenFlag) {
|
790
|
+
this.passwordTokenSeenFlag = true;
|
791
|
+
continue;
|
792
|
+
}
|
793
|
+
const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode);
|
794
|
+
if (this.passwordTokenSeenFlag) {
|
795
|
+
this.url.password += encodedCodePoints;
|
796
|
+
} else {
|
797
|
+
this.url.username += encodedCodePoints;
|
798
|
+
}
|
799
|
+
}
|
800
|
+
this.buffer = "";
|
801
|
+
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
|
802
|
+
(isSpecial(this.url) && c === 92)) {
|
803
|
+
if (this.atFlag && this.buffer === "") {
|
804
|
+
this.parseError = true;
|
805
|
+
return failure;
|
806
|
+
}
|
807
|
+
this.pointer -= countSymbols(this.buffer) + 1;
|
808
|
+
this.buffer = "";
|
809
|
+
this.state = "host";
|
810
|
+
} else {
|
811
|
+
this.buffer += cStr;
|
812
|
+
}
|
813
|
+
|
814
|
+
return true;
|
815
|
+
};
|
816
|
+
|
817
|
+
URLStateMachine.prototype["parse hostname"] =
|
818
|
+
URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) {
|
819
|
+
if (this.stateOverride && this.url.scheme === "file") {
|
820
|
+
--this.pointer;
|
821
|
+
this.state = "file host";
|
822
|
+
} else if (c === 58 && !this.arrFlag) {
|
823
|
+
if (this.buffer === "") {
|
824
|
+
this.parseError = true;
|
825
|
+
return failure;
|
826
|
+
}
|
827
|
+
|
828
|
+
const host = parseHost(this.buffer, isSpecial(this.url));
|
829
|
+
if (host === failure) {
|
830
|
+
return failure;
|
831
|
+
}
|
832
|
+
|
833
|
+
this.url.host = host;
|
834
|
+
this.buffer = "";
|
835
|
+
this.state = "port";
|
836
|
+
if (this.stateOverride === "hostname") {
|
837
|
+
return false;
|
838
|
+
}
|
839
|
+
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
|
840
|
+
(isSpecial(this.url) && c === 92)) {
|
841
|
+
--this.pointer;
|
842
|
+
if (isSpecial(this.url) && this.buffer === "") {
|
843
|
+
this.parseError = true;
|
844
|
+
return failure;
|
845
|
+
} else if (this.stateOverride && this.buffer === "" &&
|
846
|
+
(includesCredentials(this.url) || this.url.port !== null)) {
|
847
|
+
this.parseError = true;
|
848
|
+
return false;
|
849
|
+
}
|
850
|
+
|
851
|
+
const host = parseHost(this.buffer, isSpecial(this.url));
|
852
|
+
if (host === failure) {
|
853
|
+
return failure;
|
854
|
+
}
|
855
|
+
|
856
|
+
this.url.host = host;
|
857
|
+
this.buffer = "";
|
858
|
+
this.state = "path start";
|
859
|
+
if (this.stateOverride) {
|
860
|
+
return false;
|
861
|
+
}
|
862
|
+
} else {
|
863
|
+
if (c === 91) {
|
864
|
+
this.arrFlag = true;
|
865
|
+
} else if (c === 93) {
|
866
|
+
this.arrFlag = false;
|
867
|
+
}
|
868
|
+
this.buffer += cStr;
|
869
|
+
}
|
870
|
+
|
871
|
+
return true;
|
872
|
+
};
|
873
|
+
|
874
|
+
URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) {
|
875
|
+
if (isASCIIDigit(c)) {
|
876
|
+
this.buffer += cStr;
|
877
|
+
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
|
878
|
+
(isSpecial(this.url) && c === 92) ||
|
879
|
+
this.stateOverride) {
|
880
|
+
if (this.buffer !== "") {
|
881
|
+
const port = parseInt(this.buffer);
|
882
|
+
if (port > Math.pow(2, 16) - 1) {
|
883
|
+
this.parseError = true;
|
884
|
+
return failure;
|
885
|
+
}
|
886
|
+
this.url.port = port === defaultPort(this.url.scheme) ? null : port;
|
887
|
+
this.buffer = "";
|
888
|
+
}
|
889
|
+
if (this.stateOverride) {
|
890
|
+
return false;
|
891
|
+
}
|
892
|
+
this.state = "path start";
|
893
|
+
--this.pointer;
|
894
|
+
} else {
|
895
|
+
this.parseError = true;
|
896
|
+
return failure;
|
897
|
+
}
|
898
|
+
|
899
|
+
return true;
|
900
|
+
};
|
901
|
+
|
902
|
+
const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]);
|
903
|
+
|
904
|
+
URLStateMachine.prototype["parse file"] = function parseFile(c) {
|
905
|
+
this.url.scheme = "file";
|
906
|
+
|
907
|
+
if (c === 47 || c === 92) {
|
908
|
+
if (c === 92) {
|
909
|
+
this.parseError = true;
|
910
|
+
}
|
911
|
+
this.state = "file slash";
|
912
|
+
} else if (this.base !== null && this.base.scheme === "file") {
|
913
|
+
if (isNaN(c)) {
|
914
|
+
this.url.host = this.base.host;
|
915
|
+
this.url.path = this.base.path.slice();
|
916
|
+
this.url.query = this.base.query;
|
917
|
+
} else if (c === 63) {
|
918
|
+
this.url.host = this.base.host;
|
919
|
+
this.url.path = this.base.path.slice();
|
920
|
+
this.url.query = "";
|
921
|
+
this.state = "query";
|
922
|
+
} else if (c === 35) {
|
923
|
+
this.url.host = this.base.host;
|
924
|
+
this.url.path = this.base.path.slice();
|
925
|
+
this.url.query = this.base.query;
|
926
|
+
this.url.fragment = "";
|
927
|
+
this.state = "fragment";
|
928
|
+
} else {
|
929
|
+
if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points
|
930
|
+
!isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) ||
|
931
|
+
(this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points
|
932
|
+
!fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) {
|
933
|
+
this.url.host = this.base.host;
|
934
|
+
this.url.path = this.base.path.slice();
|
935
|
+
shortenPath(this.url);
|
936
|
+
} else {
|
937
|
+
this.parseError = true;
|
938
|
+
}
|
939
|
+
|
940
|
+
this.state = "path";
|
941
|
+
--this.pointer;
|
942
|
+
}
|
943
|
+
} else {
|
944
|
+
this.state = "path";
|
945
|
+
--this.pointer;
|
946
|
+
}
|
947
|
+
|
948
|
+
return true;
|
949
|
+
};
|
950
|
+
|
951
|
+
URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) {
|
952
|
+
if (c === 47 || c === 92) {
|
953
|
+
if (c === 92) {
|
954
|
+
this.parseError = true;
|
955
|
+
}
|
956
|
+
this.state = "file host";
|
957
|
+
} else {
|
958
|
+
if (this.base !== null && this.base.scheme === "file") {
|
959
|
+
if (isNormalizedWindowsDriveLetterString(this.base.path[0])) {
|
960
|
+
this.url.path.push(this.base.path[0]);
|
961
|
+
} else {
|
962
|
+
this.url.host = this.base.host;
|
963
|
+
}
|
964
|
+
}
|
965
|
+
this.state = "path";
|
966
|
+
--this.pointer;
|
967
|
+
}
|
968
|
+
|
969
|
+
return true;
|
970
|
+
};
|
971
|
+
|
972
|
+
URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) {
|
973
|
+
if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) {
|
974
|
+
--this.pointer;
|
975
|
+
if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) {
|
976
|
+
this.parseError = true;
|
977
|
+
this.state = "path";
|
978
|
+
} else if (this.buffer === "") {
|
979
|
+
this.url.host = "";
|
980
|
+
if (this.stateOverride) {
|
981
|
+
return false;
|
982
|
+
}
|
983
|
+
this.state = "path start";
|
984
|
+
} else {
|
985
|
+
let host = parseHost(this.buffer, isSpecial(this.url));
|
986
|
+
if (host === failure) {
|
987
|
+
return failure;
|
988
|
+
}
|
989
|
+
if (host === "localhost") {
|
990
|
+
host = "";
|
991
|
+
}
|
992
|
+
this.url.host = host;
|
993
|
+
|
994
|
+
if (this.stateOverride) {
|
995
|
+
return false;
|
996
|
+
}
|
997
|
+
|
998
|
+
this.buffer = "";
|
999
|
+
this.state = "path start";
|
1000
|
+
}
|
1001
|
+
} else {
|
1002
|
+
this.buffer += cStr;
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
return true;
|
1006
|
+
};
|
1007
|
+
|
1008
|
+
URLStateMachine.prototype["parse path start"] = function parsePathStart(c) {
|
1009
|
+
if (isSpecial(this.url)) {
|
1010
|
+
if (c === 92) {
|
1011
|
+
this.parseError = true;
|
1012
|
+
}
|
1013
|
+
this.state = "path";
|
1014
|
+
|
1015
|
+
if (c !== 47 && c !== 92) {
|
1016
|
+
--this.pointer;
|
1017
|
+
}
|
1018
|
+
} else if (!this.stateOverride && c === 63) {
|
1019
|
+
this.url.query = "";
|
1020
|
+
this.state = "query";
|
1021
|
+
} else if (!this.stateOverride && c === 35) {
|
1022
|
+
this.url.fragment = "";
|
1023
|
+
this.state = "fragment";
|
1024
|
+
} else if (c !== undefined) {
|
1025
|
+
this.state = "path";
|
1026
|
+
if (c !== 47) {
|
1027
|
+
--this.pointer;
|
1028
|
+
}
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
return true;
|
1032
|
+
};
|
1033
|
+
|
1034
|
+
URLStateMachine.prototype["parse path"] = function parsePath(c) {
|
1035
|
+
if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) ||
|
1036
|
+
(!this.stateOverride && (c === 63 || c === 35))) {
|
1037
|
+
if (isSpecial(this.url) && c === 92) {
|
1038
|
+
this.parseError = true;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
if (isDoubleDot(this.buffer)) {
|
1042
|
+
shortenPath(this.url);
|
1043
|
+
if (c !== 47 && !(isSpecial(this.url) && c === 92)) {
|
1044
|
+
this.url.path.push("");
|
1045
|
+
}
|
1046
|
+
} else if (isSingleDot(this.buffer) && c !== 47 &&
|
1047
|
+
!(isSpecial(this.url) && c === 92)) {
|
1048
|
+
this.url.path.push("");
|
1049
|
+
} else if (!isSingleDot(this.buffer)) {
|
1050
|
+
if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) {
|
1051
|
+
if (this.url.host !== "" && this.url.host !== null) {
|
1052
|
+
this.parseError = true;
|
1053
|
+
this.url.host = "";
|
1054
|
+
}
|
1055
|
+
this.buffer = this.buffer[0] + ":";
|
1056
|
+
}
|
1057
|
+
this.url.path.push(this.buffer);
|
1058
|
+
}
|
1059
|
+
this.buffer = "";
|
1060
|
+
if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) {
|
1061
|
+
while (this.url.path.length > 1 && this.url.path[0] === "") {
|
1062
|
+
this.parseError = true;
|
1063
|
+
this.url.path.shift();
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
if (c === 63) {
|
1067
|
+
this.url.query = "";
|
1068
|
+
this.state = "query";
|
1069
|
+
}
|
1070
|
+
if (c === 35) {
|
1071
|
+
this.url.fragment = "";
|
1072
|
+
this.state = "fragment";
|
1073
|
+
}
|
1074
|
+
} else {
|
1075
|
+
// TODO: If c is not a URL code point and not "%", parse error.
|
1076
|
+
|
1077
|
+
if (c === 37 &&
|
1078
|
+
(!isASCIIHex(this.input[this.pointer + 1]) ||
|
1079
|
+
!isASCIIHex(this.input[this.pointer + 2]))) {
|
1080
|
+
this.parseError = true;
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
this.buffer += percentEncodeChar(c, isPathPercentEncode);
|
1084
|
+
}
|
1085
|
+
|
1086
|
+
return true;
|
1087
|
+
};
|
1088
|
+
|
1089
|
+
URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) {
|
1090
|
+
if (c === 63) {
|
1091
|
+
this.url.query = "";
|
1092
|
+
this.state = "query";
|
1093
|
+
} else if (c === 35) {
|
1094
|
+
this.url.fragment = "";
|
1095
|
+
this.state = "fragment";
|
1096
|
+
} else {
|
1097
|
+
// TODO: Add: not a URL code point
|
1098
|
+
if (!isNaN(c) && c !== 37) {
|
1099
|
+
this.parseError = true;
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
if (c === 37 &&
|
1103
|
+
(!isASCIIHex(this.input[this.pointer + 1]) ||
|
1104
|
+
!isASCIIHex(this.input[this.pointer + 2]))) {
|
1105
|
+
this.parseError = true;
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
if (!isNaN(c)) {
|
1109
|
+
this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode);
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
|
1113
|
+
return true;
|
1114
|
+
};
|
1115
|
+
|
1116
|
+
URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) {
|
1117
|
+
if (isNaN(c) || (!this.stateOverride && c === 35)) {
|
1118
|
+
if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") {
|
1119
|
+
this.encodingOverride = "utf-8";
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead
|
1123
|
+
for (let i = 0; i < buffer.length; ++i) {
|
1124
|
+
if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 ||
|
1125
|
+
buffer[i] === 0x3C || buffer[i] === 0x3E) {
|
1126
|
+
this.url.query += percentEncode(buffer[i]);
|
1127
|
+
} else {
|
1128
|
+
this.url.query += String.fromCodePoint(buffer[i]);
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
this.buffer = "";
|
1133
|
+
if (c === 35) {
|
1134
|
+
this.url.fragment = "";
|
1135
|
+
this.state = "fragment";
|
1136
|
+
}
|
1137
|
+
} else {
|
1138
|
+
// TODO: If c is not a URL code point and not "%", parse error.
|
1139
|
+
if (c === 37 &&
|
1140
|
+
(!isASCIIHex(this.input[this.pointer + 1]) ||
|
1141
|
+
!isASCIIHex(this.input[this.pointer + 2]))) {
|
1142
|
+
this.parseError = true;
|
1143
|
+
}
|
1144
|
+
|
1145
|
+
this.buffer += cStr;
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
return true;
|
1149
|
+
};
|
1150
|
+
|
1151
|
+
URLStateMachine.prototype["parse fragment"] = function parseFragment(c) {
|
1152
|
+
if (isNaN(c)) { // do nothing
|
1153
|
+
} else if (c === 0x0) {
|
1154
|
+
this.parseError = true;
|
1155
|
+
} else {
|
1156
|
+
// TODO: If c is not a URL code point and not "%", parse error.
|
1157
|
+
if (c === 37 &&
|
1158
|
+
(!isASCIIHex(this.input[this.pointer + 1]) ||
|
1159
|
+
!isASCIIHex(this.input[this.pointer + 2]))) {
|
1160
|
+
this.parseError = true;
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode);
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
return true;
|
1167
|
+
};
|
1168
|
+
|
1169
|
+
function serializeURL(url, excludeFragment) {
|
1170
|
+
let output = url.scheme + ":";
|
1171
|
+
if (url.host !== null) {
|
1172
|
+
output += "//";
|
1173
|
+
|
1174
|
+
if (url.username !== "" || url.password !== "") {
|
1175
|
+
output += url.username;
|
1176
|
+
if (url.password !== "") {
|
1177
|
+
output += ":" + url.password;
|
1178
|
+
}
|
1179
|
+
output += "@";
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
output += serializeHost(url.host);
|
1183
|
+
|
1184
|
+
if (url.port !== null) {
|
1185
|
+
output += ":" + url.port;
|
1186
|
+
}
|
1187
|
+
} else if (url.host === null && url.scheme === "file") {
|
1188
|
+
output += "//";
|
1189
|
+
}
|
1190
|
+
|
1191
|
+
if (url.cannotBeABaseURL) {
|
1192
|
+
output += url.path[0];
|
1193
|
+
} else {
|
1194
|
+
for (const string of url.path) {
|
1195
|
+
output += "/" + string;
|
1196
|
+
}
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
if (url.query !== null) {
|
1200
|
+
output += "?" + url.query;
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
if (!excludeFragment && url.fragment !== null) {
|
1204
|
+
output += "#" + url.fragment;
|
1205
|
+
}
|
1206
|
+
|
1207
|
+
return output;
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
function serializeOrigin(tuple) {
|
1211
|
+
let result = tuple.scheme + "://";
|
1212
|
+
result += serializeHost(tuple.host);
|
1213
|
+
|
1214
|
+
if (tuple.port !== null) {
|
1215
|
+
result += ":" + tuple.port;
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
return result;
|
1219
|
+
}
|
1220
|
+
|
1221
|
+
module.exports.serializeURL = serializeURL;
|
1222
|
+
|
1223
|
+
module.exports.serializeURLOrigin = function (url) {
|
1224
|
+
// https://url.spec.whatwg.org/#concept-url-origin
|
1225
|
+
switch (url.scheme) {
|
1226
|
+
case "blob":
|
1227
|
+
try {
|
1228
|
+
return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0]));
|
1229
|
+
} catch (e) {
|
1230
|
+
// serializing an opaque origin returns "null"
|
1231
|
+
return "null";
|
1232
|
+
}
|
1233
|
+
case "ftp":
|
1234
|
+
case "gopher":
|
1235
|
+
case "http":
|
1236
|
+
case "https":
|
1237
|
+
case "ws":
|
1238
|
+
case "wss":
|
1239
|
+
return serializeOrigin({
|
1240
|
+
scheme: url.scheme,
|
1241
|
+
host: url.host,
|
1242
|
+
port: url.port
|
1243
|
+
});
|
1244
|
+
case "file":
|
1245
|
+
// spec says "exercise to the reader", chrome says "file://"
|
1246
|
+
return "file://";
|
1247
|
+
default:
|
1248
|
+
// serializing an opaque origin returns "null"
|
1249
|
+
return "null";
|
1250
|
+
}
|
1251
|
+
};
|
1252
|
+
|
1253
|
+
module.exports.basicURLParse = function (input, options) {
|
1254
|
+
if (options === undefined) {
|
1255
|
+
options = {};
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride);
|
1259
|
+
if (usm.failure) {
|
1260
|
+
return "failure";
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
return usm.url;
|
1264
|
+
};
|
1265
|
+
|
1266
|
+
module.exports.setTheUsername = function (url, username) {
|
1267
|
+
url.username = "";
|
1268
|
+
const decoded = punycode.ucs2.decode(username);
|
1269
|
+
for (let i = 0; i < decoded.length; ++i) {
|
1270
|
+
url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
|
1271
|
+
}
|
1272
|
+
};
|
1273
|
+
|
1274
|
+
module.exports.setThePassword = function (url, password) {
|
1275
|
+
url.password = "";
|
1276
|
+
const decoded = punycode.ucs2.decode(password);
|
1277
|
+
for (let i = 0; i < decoded.length; ++i) {
|
1278
|
+
url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
|
1279
|
+
}
|
1280
|
+
};
|
1281
|
+
|
1282
|
+
module.exports.serializeHost = serializeHost;
|
1283
|
+
|
1284
|
+
module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort;
|
1285
|
+
|
1286
|
+
module.exports.serializeInteger = function (integer) {
|
1287
|
+
return String(integer);
|
1288
|
+
};
|
1289
|
+
|
1290
|
+
module.exports.parseURL = function (input, options) {
|
1291
|
+
if (options === undefined) {
|
1292
|
+
options = {};
|
1293
|
+
}
|
1294
|
+
|
1295
|
+
// We don't handle blobs, so this just delegates:
|
1296
|
+
return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride });
|
1297
|
+
};
|