tough-cookie 4.0.0 → 4.1.2
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 +253 -239
- package/lib/cookie.js +109 -24
- package/lib/memstore.js +57 -5
- package/lib/permuteDomain.js +9 -14
- package/lib/pubsuffix-psl.js +36 -1
- package/lib/utilHelper.js +39 -0
- package/lib/validators.js +95 -0
- package/lib/version.js +1 -1
- package/package.json +4 -3
package/lib/cookie.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Copyright (c) 2015, Salesforce.com, Inc.
|
|
2
|
+
* Copyright (c) 2015-2020, Salesforce.com, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -29,15 +29,16 @@
|
|
|
29
29
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
30
30
|
*/
|
|
31
31
|
"use strict";
|
|
32
|
-
const punycode = require("punycode");
|
|
33
|
-
const urlParse = require("url")
|
|
34
|
-
const util = require("util");
|
|
32
|
+
const punycode = require("punycode/");
|
|
33
|
+
const urlParse = require("url-parse");
|
|
35
34
|
const pubsuffix = require("./pubsuffix-psl");
|
|
36
35
|
const Store = require("./store").Store;
|
|
37
36
|
const MemoryCookieStore = require("./memstore").MemoryCookieStore;
|
|
38
37
|
const pathMatch = require("./pathMatch").pathMatch;
|
|
38
|
+
const validators = require("./validators.js");
|
|
39
39
|
const VERSION = require("./version");
|
|
40
40
|
const { fromCallback } = require("universalify");
|
|
41
|
+
const { getCustomInspectSymbol } = require("./utilHelper");
|
|
41
42
|
|
|
42
43
|
// From RFC6265 S4.1.1
|
|
43
44
|
// note that it excludes \x3B ";"
|
|
@@ -79,6 +80,7 @@ const SAME_SITE_CONTEXT_VAL_ERR =
|
|
|
79
80
|
'Invalid sameSiteContext option for getCookies(); expected one of "strict", "lax", or "none"';
|
|
80
81
|
|
|
81
82
|
function checkSameSiteContext(value) {
|
|
83
|
+
validators.validate(validators.isNonEmptyString(value), value);
|
|
82
84
|
const context = String(value).toLowerCase();
|
|
83
85
|
if (context === "none" || context === "lax" || context === "strict") {
|
|
84
86
|
return context;
|
|
@@ -97,7 +99,23 @@ const PrefixSecurityEnum = Object.freeze({
|
|
|
97
99
|
// * all capturing groups converted to non-capturing -- "(?:)"
|
|
98
100
|
// * support for IPv6 Scoped Literal ("%eth1") removed
|
|
99
101
|
// * lowercase hexadecimal only
|
|
100
|
-
|
|
102
|
+
const IP_REGEX_LOWERCASE = /(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-f\d]{1,4}:){7}(?:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,2}|:)|(?:[a-f\d]{1,4}:){4}(?:(?::[a-f\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,3}|:)|(?:[a-f\d]{1,4}:){3}(?:(?::[a-f\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,4}|:)|(?:[a-f\d]{1,4}:){2}(?:(?::[a-f\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,5}|:)|(?:[a-f\d]{1,4}:){1}(?:(?::[a-f\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,6}|:)|(?::(?:(?::[a-f\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,7}|:)))$)/;
|
|
103
|
+
const IP_V6_REGEX = `
|
|
104
|
+
\\[?(?:
|
|
105
|
+
(?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|
|
|
106
|
+
(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|
|
|
107
|
+
(?:[a-fA-F\\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,2}|:)|
|
|
108
|
+
(?:[a-fA-F\\d]{1,4}:){4}(?:(?::[a-fA-F\\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,3}|:)|
|
|
109
|
+
(?:[a-fA-F\\d]{1,4}:){3}(?:(?::[a-fA-F\\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,4}|:)|
|
|
110
|
+
(?:[a-fA-F\\d]{1,4}:){2}(?:(?::[a-fA-F\\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,5}|:)|
|
|
111
|
+
(?:[a-fA-F\\d]{1,4}:){1}(?:(?::[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,6}|:)|
|
|
112
|
+
(?::(?:(?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:))
|
|
113
|
+
)(?:%[0-9a-zA-Z]{1,})?\\]?
|
|
114
|
+
`
|
|
115
|
+
.replace(/\s*\/\/.*$/gm, "")
|
|
116
|
+
.replace(/\n/g, "")
|
|
117
|
+
.trim();
|
|
118
|
+
const IP_V6_REGEX_OBJECT = new RegExp(`^${IP_V6_REGEX}$`);
|
|
101
119
|
|
|
102
120
|
/*
|
|
103
121
|
* Parses a Natural number (i.e., non-negative integer) with either the
|
|
@@ -301,6 +319,7 @@ function parseDate(str) {
|
|
|
301
319
|
}
|
|
302
320
|
|
|
303
321
|
function formatDate(date) {
|
|
322
|
+
validators.validate(validators.isDate(date), date);
|
|
304
323
|
return date.toUTCString();
|
|
305
324
|
}
|
|
306
325
|
|
|
@@ -311,6 +330,10 @@ function canonicalDomain(str) {
|
|
|
311
330
|
}
|
|
312
331
|
str = str.trim().replace(/^\./, ""); // S4.1.2.3 & S5.2.3: ignore leading .
|
|
313
332
|
|
|
333
|
+
if (IP_V6_REGEX_OBJECT.test(str)) {
|
|
334
|
+
str = str.replace("[", "").replace("]", "");
|
|
335
|
+
}
|
|
336
|
+
|
|
314
337
|
// convert to IDN if any non-ASCII characters
|
|
315
338
|
if (punycode && /[^\u0001-\u007f]/.test(str)) {
|
|
316
339
|
str = punycode.toASCII(str);
|
|
@@ -345,7 +368,7 @@ function domainMatch(str, domStr, canonicalize) {
|
|
|
345
368
|
/* " o All of the following [three] conditions hold:" */
|
|
346
369
|
|
|
347
370
|
/* "* The domain string is a suffix of the string" */
|
|
348
|
-
const idx = str.
|
|
371
|
+
const idx = str.lastIndexOf(domStr);
|
|
349
372
|
if (idx <= 0) {
|
|
350
373
|
return false; // it's a non-match (-1) or prefix (0)
|
|
351
374
|
}
|
|
@@ -359,7 +382,7 @@ function domainMatch(str, domStr, canonicalize) {
|
|
|
359
382
|
|
|
360
383
|
/* " * The last character of the string that is not included in the
|
|
361
384
|
* domain string is a %x2E (".") character." */
|
|
362
|
-
if (str.substr(idx-1,1) !==
|
|
385
|
+
if (str.substr(idx - 1, 1) !== ".") {
|
|
363
386
|
return false; // doesn't align on "."
|
|
364
387
|
}
|
|
365
388
|
|
|
@@ -403,6 +426,7 @@ function defaultPath(path) {
|
|
|
403
426
|
}
|
|
404
427
|
|
|
405
428
|
function trimTerminator(str) {
|
|
429
|
+
if (validators.isEmptyString(str)) return str;
|
|
406
430
|
for (let t = 0; t < TERMINATORS.length; t++) {
|
|
407
431
|
const terminatorIdx = str.indexOf(TERMINATORS[t]);
|
|
408
432
|
if (terminatorIdx !== -1) {
|
|
@@ -415,6 +439,7 @@ function trimTerminator(str) {
|
|
|
415
439
|
|
|
416
440
|
function parseCookiePair(cookiePair, looseMode) {
|
|
417
441
|
cookiePair = trimTerminator(cookiePair);
|
|
442
|
+
validators.validate(validators.isString(cookiePair), cookiePair);
|
|
418
443
|
|
|
419
444
|
let firstEq = cookiePair.indexOf("=");
|
|
420
445
|
if (looseMode) {
|
|
@@ -454,6 +479,11 @@ function parse(str, options) {
|
|
|
454
479
|
if (!options || typeof options !== "object") {
|
|
455
480
|
options = {};
|
|
456
481
|
}
|
|
482
|
+
|
|
483
|
+
if (validators.isEmptyString(str) || !validators.isString(str)) {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
|
|
457
487
|
str = str.trim();
|
|
458
488
|
|
|
459
489
|
// We use a regex to parse the "name-value-pair" part of S5.2
|
|
@@ -589,11 +619,11 @@ function parse(str, options) {
|
|
|
589
619
|
case "lax":
|
|
590
620
|
c.sameSite = "lax";
|
|
591
621
|
break;
|
|
622
|
+
case "none":
|
|
623
|
+
c.sameSite = "none";
|
|
624
|
+
break;
|
|
592
625
|
default:
|
|
593
|
-
|
|
594
|
-
// "If cookie-av's attribute-value is not a case-insensitive match
|
|
595
|
-
// for "Strict" or "Lax", ignore the "cookie-av"."
|
|
596
|
-
// This effectively sets it to 'none' from the prototype.
|
|
626
|
+
c.sameSite = undefined;
|
|
597
627
|
break;
|
|
598
628
|
}
|
|
599
629
|
break;
|
|
@@ -616,6 +646,7 @@ function parse(str, options) {
|
|
|
616
646
|
* @returns boolean
|
|
617
647
|
*/
|
|
618
648
|
function isSecurePrefixConditionMet(cookie) {
|
|
649
|
+
validators.validate(validators.isObject(cookie), cookie);
|
|
619
650
|
return !cookie.key.startsWith("__Secure-") || cookie.secure;
|
|
620
651
|
}
|
|
621
652
|
|
|
@@ -631,6 +662,7 @@ function isSecurePrefixConditionMet(cookie) {
|
|
|
631
662
|
* @returns boolean
|
|
632
663
|
*/
|
|
633
664
|
function isHostPrefixConditionMet(cookie) {
|
|
665
|
+
validators.validate(validators.isObject(cookie));
|
|
634
666
|
return (
|
|
635
667
|
!cookie.key.startsWith("__Host-") ||
|
|
636
668
|
(cookie.secure &&
|
|
@@ -652,7 +684,7 @@ function jsonParse(str) {
|
|
|
652
684
|
}
|
|
653
685
|
|
|
654
686
|
function fromJSON(str) {
|
|
655
|
-
if (!str) {
|
|
687
|
+
if (!str || validators.isEmptyString(str)) {
|
|
656
688
|
return null;
|
|
657
689
|
}
|
|
658
690
|
|
|
@@ -698,6 +730,8 @@ function fromJSON(str) {
|
|
|
698
730
|
*/
|
|
699
731
|
|
|
700
732
|
function cookieCompare(a, b) {
|
|
733
|
+
validators.validate(validators.isObject(a), a);
|
|
734
|
+
validators.validate(validators.isObject(b), b);
|
|
701
735
|
let cmp = 0;
|
|
702
736
|
|
|
703
737
|
// descending for length: b CMP a
|
|
@@ -725,6 +759,7 @@ function cookieCompare(a, b) {
|
|
|
725
759
|
// Gives the permutation of all possible pathMatch()es of a given path. The
|
|
726
760
|
// array is in longest-to-shortest order. Handy for indexing.
|
|
727
761
|
function permutePath(path) {
|
|
762
|
+
validators.validate(validators.isString(path));
|
|
728
763
|
if (path === "/") {
|
|
729
764
|
return ["/"];
|
|
730
765
|
}
|
|
@@ -772,13 +807,14 @@ const cookieDefaults = {
|
|
|
772
807
|
pathIsDefault: null,
|
|
773
808
|
creation: null,
|
|
774
809
|
lastAccessed: null,
|
|
775
|
-
sameSite:
|
|
810
|
+
sameSite: undefined
|
|
776
811
|
};
|
|
777
812
|
|
|
778
813
|
class Cookie {
|
|
779
814
|
constructor(options = {}) {
|
|
780
|
-
|
|
781
|
-
|
|
815
|
+
const customInspectSymbol = getCustomInspectSymbol();
|
|
816
|
+
if (customInspectSymbol) {
|
|
817
|
+
this[customInspectSymbol] = this.inspect;
|
|
782
818
|
}
|
|
783
819
|
|
|
784
820
|
Object.assign(this, cookieDefaults, options);
|
|
@@ -1060,9 +1096,13 @@ class CookieJar {
|
|
|
1060
1096
|
if (typeof options === "boolean") {
|
|
1061
1097
|
options = { rejectPublicSuffixes: options };
|
|
1062
1098
|
}
|
|
1099
|
+
validators.validate(validators.isObject(options), options);
|
|
1063
1100
|
this.rejectPublicSuffixes = options.rejectPublicSuffixes;
|
|
1064
1101
|
this.enableLooseMode = !!options.looseMode;
|
|
1065
|
-
this.allowSpecialUseDomain =
|
|
1102
|
+
this.allowSpecialUseDomain =
|
|
1103
|
+
typeof options.allowSpecialUseDomain === "boolean"
|
|
1104
|
+
? options.allowSpecialUseDomain
|
|
1105
|
+
: true;
|
|
1066
1106
|
this.store = store || new MemoryCookieStore();
|
|
1067
1107
|
this.prefixSecurity = getNormalizedPrefixSecurity(options.prefixSecurity);
|
|
1068
1108
|
this._cloneSync = syncWrap("clone");
|
|
@@ -1076,13 +1116,31 @@ class CookieJar {
|
|
|
1076
1116
|
}
|
|
1077
1117
|
|
|
1078
1118
|
setCookie(cookie, url, options, cb) {
|
|
1119
|
+
validators.validate(validators.isNonEmptyString(url), cb, options);
|
|
1079
1120
|
let err;
|
|
1121
|
+
|
|
1122
|
+
if (validators.isFunction(url)) {
|
|
1123
|
+
cb = url;
|
|
1124
|
+
return cb(new Error("No URL was specified"));
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1080
1127
|
const context = getCookieContext(url);
|
|
1081
|
-
if (
|
|
1128
|
+
if (validators.isFunction(options)) {
|
|
1082
1129
|
cb = options;
|
|
1083
1130
|
options = {};
|
|
1084
1131
|
}
|
|
1085
1132
|
|
|
1133
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1134
|
+
|
|
1135
|
+
if (
|
|
1136
|
+
!validators.isNonEmptyString(cookie) &&
|
|
1137
|
+
!validators.isObject(cookie) &&
|
|
1138
|
+
cookie instanceof String &&
|
|
1139
|
+
cookie.length == 0
|
|
1140
|
+
) {
|
|
1141
|
+
return cb(null);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1086
1144
|
const host = canonicalDomain(context.hostname);
|
|
1087
1145
|
const loose = options.loose || this.enableLooseMode;
|
|
1088
1146
|
|
|
@@ -1119,8 +1177,11 @@ class CookieJar {
|
|
|
1119
1177
|
|
|
1120
1178
|
// S5.3 step 5: public suffixes
|
|
1121
1179
|
if (this.rejectPublicSuffixes && cookie.domain) {
|
|
1122
|
-
const suffix = pubsuffix.getPublicSuffix(cookie.cdomain()
|
|
1123
|
-
|
|
1180
|
+
const suffix = pubsuffix.getPublicSuffix(cookie.cdomain(), {
|
|
1181
|
+
allowSpecialUseDomain: this.allowSpecialUseDomain,
|
|
1182
|
+
ignoreError: options.ignoreError
|
|
1183
|
+
});
|
|
1184
|
+
if (suffix == null && !IP_V6_REGEX_OBJECT.test(cookie.domain)) {
|
|
1124
1185
|
// e.g. "com"
|
|
1125
1186
|
err = new Error("Cookie has domain set to a public suffix");
|
|
1126
1187
|
return cb(options.ignoreError ? null : err);
|
|
@@ -1163,7 +1224,11 @@ class CookieJar {
|
|
|
1163
1224
|
}
|
|
1164
1225
|
|
|
1165
1226
|
// 6252bis-02 S5.4 Step 13 & 14:
|
|
1166
|
-
if (
|
|
1227
|
+
if (
|
|
1228
|
+
cookie.sameSite !== "none" &&
|
|
1229
|
+
cookie.sameSite !== undefined &&
|
|
1230
|
+
sameSiteContext
|
|
1231
|
+
) {
|
|
1167
1232
|
// "If the cookie's "same-site-flag" is not "None", and the cookie
|
|
1168
1233
|
// is being set from a context whose "site for cookies" is not an
|
|
1169
1234
|
// exact match for request-uri's host's registered domain, then
|
|
@@ -1249,11 +1314,14 @@ class CookieJar {
|
|
|
1249
1314
|
|
|
1250
1315
|
// RFC6365 S5.4
|
|
1251
1316
|
getCookies(url, options, cb) {
|
|
1317
|
+
validators.validate(validators.isNonEmptyString(url), cb, url);
|
|
1252
1318
|
const context = getCookieContext(url);
|
|
1253
|
-
if (
|
|
1319
|
+
if (validators.isFunction(options)) {
|
|
1254
1320
|
cb = options;
|
|
1255
1321
|
options = {};
|
|
1256
1322
|
}
|
|
1323
|
+
validators.validate(validators.isObject(options), cb, options);
|
|
1324
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1257
1325
|
|
|
1258
1326
|
const host = canonicalDomain(context.hostname);
|
|
1259
1327
|
const path = context.pathname || "/";
|
|
@@ -1369,6 +1437,7 @@ class CookieJar {
|
|
|
1369
1437
|
|
|
1370
1438
|
getCookieString(...args) {
|
|
1371
1439
|
const cb = args.pop();
|
|
1440
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1372
1441
|
const next = function(err, cookies) {
|
|
1373
1442
|
if (err) {
|
|
1374
1443
|
cb(err);
|
|
@@ -1388,6 +1457,7 @@ class CookieJar {
|
|
|
1388
1457
|
|
|
1389
1458
|
getSetCookieStrings(...args) {
|
|
1390
1459
|
const cb = args.pop();
|
|
1460
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1391
1461
|
const next = function(err, cookies) {
|
|
1392
1462
|
if (err) {
|
|
1393
1463
|
cb(err);
|
|
@@ -1405,8 +1475,9 @@ class CookieJar {
|
|
|
1405
1475
|
}
|
|
1406
1476
|
|
|
1407
1477
|
serialize(cb) {
|
|
1478
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1408
1479
|
let type = this.store.constructor.name;
|
|
1409
|
-
if (type
|
|
1480
|
+
if (validators.isObject(type)) {
|
|
1410
1481
|
type = null;
|
|
1411
1482
|
}
|
|
1412
1483
|
|
|
@@ -1422,6 +1493,9 @@ class CookieJar {
|
|
|
1422
1493
|
|
|
1423
1494
|
// CookieJar configuration:
|
|
1424
1495
|
rejectPublicSuffixes: !!this.rejectPublicSuffixes,
|
|
1496
|
+
enableLooseMode: !!this.enableLooseMode,
|
|
1497
|
+
allowSpecialUseDomain: !!this.allowSpecialUseDomain,
|
|
1498
|
+
prefixSecurity: getNormalizedPrefixSecurity(this.prefixSecurity),
|
|
1425
1499
|
|
|
1426
1500
|
// this gets filled from getAllCookies:
|
|
1427
1501
|
cookies: []
|
|
@@ -1524,6 +1598,7 @@ class CookieJar {
|
|
|
1524
1598
|
}
|
|
1525
1599
|
|
|
1526
1600
|
removeAllCookies(cb) {
|
|
1601
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1527
1602
|
const store = this.store;
|
|
1528
1603
|
|
|
1529
1604
|
// Check that the store implements its own removeAllCookies(). The default
|
|
@@ -1577,6 +1652,7 @@ class CookieJar {
|
|
|
1577
1652
|
cb = store;
|
|
1578
1653
|
store = null;
|
|
1579
1654
|
}
|
|
1655
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1580
1656
|
|
|
1581
1657
|
let serialized;
|
|
1582
1658
|
if (typeof strOrObj === "string") {
|
|
@@ -1588,7 +1664,12 @@ class CookieJar {
|
|
|
1588
1664
|
serialized = strOrObj;
|
|
1589
1665
|
}
|
|
1590
1666
|
|
|
1591
|
-
const jar = new CookieJar(store,
|
|
1667
|
+
const jar = new CookieJar(store, {
|
|
1668
|
+
rejectPublicSuffixes: serialized.rejectPublicSuffixes,
|
|
1669
|
+
looseMode: serialized.enableLooseMode,
|
|
1670
|
+
allowSpecialUseDomain: serialized.allowSpecialUseDomain,
|
|
1671
|
+
prefixSecurity: serialized.prefixSecurity
|
|
1672
|
+
});
|
|
1592
1673
|
jar._importCookies(serialized, err => {
|
|
1593
1674
|
if (err) {
|
|
1594
1675
|
return cb(err);
|
|
@@ -1600,7 +1681,10 @@ class CookieJar {
|
|
|
1600
1681
|
static deserializeSync(strOrObj, store) {
|
|
1601
1682
|
const serialized =
|
|
1602
1683
|
typeof strOrObj === "string" ? JSON.parse(strOrObj) : strOrObj;
|
|
1603
|
-
const jar = new CookieJar(store,
|
|
1684
|
+
const jar = new CookieJar(store, {
|
|
1685
|
+
rejectPublicSuffixes: serialized.rejectPublicSuffixes,
|
|
1686
|
+
looseMode: serialized.enableLooseMode
|
|
1687
|
+
});
|
|
1604
1688
|
|
|
1605
1689
|
// catch this mistake early:
|
|
1606
1690
|
if (!jar.store.synchronous) {
|
|
@@ -1669,3 +1753,4 @@ exports.permuteDomain = require("./permuteDomain").permuteDomain;
|
|
|
1669
1753
|
exports.permutePath = permutePath;
|
|
1670
1754
|
exports.canonicalDomain = canonicalDomain;
|
|
1671
1755
|
exports.PrefixSecurityEnum = PrefixSecurityEnum;
|
|
1756
|
+
exports.ParameterError = validators.ParameterError;
|
package/lib/memstore.js
CHANGED
|
@@ -33,19 +33,21 @@ const { fromCallback } = require("universalify");
|
|
|
33
33
|
const Store = require("./store").Store;
|
|
34
34
|
const permuteDomain = require("./permuteDomain").permuteDomain;
|
|
35
35
|
const pathMatch = require("./pathMatch").pathMatch;
|
|
36
|
-
const
|
|
36
|
+
const { getCustomInspectSymbol, getUtilInspect } = require("./utilHelper");
|
|
37
37
|
|
|
38
38
|
class MemoryCookieStore extends Store {
|
|
39
39
|
constructor() {
|
|
40
40
|
super();
|
|
41
41
|
this.synchronous = true;
|
|
42
42
|
this.idx = {};
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const customInspectSymbol = getCustomInspectSymbol();
|
|
44
|
+
if (customInspectSymbol) {
|
|
45
|
+
this[customInspectSymbol] = this.inspect;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
inspect() {
|
|
50
|
+
const util = { inspect: getUtilInspect(inspectFallback) };
|
|
49
51
|
return `{ idx: ${util.inspect(this.idx, false, 2)} }`;
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -62,7 +64,7 @@ class MemoryCookieStore extends Store {
|
|
|
62
64
|
const results = [];
|
|
63
65
|
if (typeof allowSpecialUseDomain === "function") {
|
|
64
66
|
cb = allowSpecialUseDomain;
|
|
65
|
-
allowSpecialUseDomain =
|
|
67
|
+
allowSpecialUseDomain = true;
|
|
66
68
|
}
|
|
67
69
|
if (!domain) {
|
|
68
70
|
return cb(null, []);
|
|
@@ -184,7 +186,57 @@ class MemoryCookieStore extends Store {
|
|
|
184
186
|
"removeAllCookies",
|
|
185
187
|
"getAllCookies"
|
|
186
188
|
].forEach(name => {
|
|
187
|
-
MemoryCookieStore[name] = fromCallback(
|
|
189
|
+
MemoryCookieStore.prototype[name] = fromCallback(
|
|
190
|
+
MemoryCookieStore.prototype[name]
|
|
191
|
+
);
|
|
188
192
|
});
|
|
189
193
|
|
|
190
194
|
exports.MemoryCookieStore = MemoryCookieStore;
|
|
195
|
+
|
|
196
|
+
function inspectFallback(val) {
|
|
197
|
+
const domains = Object.keys(val);
|
|
198
|
+
if (domains.length === 0) {
|
|
199
|
+
return "{}";
|
|
200
|
+
}
|
|
201
|
+
let result = "{\n";
|
|
202
|
+
Object.keys(val).forEach((domain, i) => {
|
|
203
|
+
result += formatDomain(domain, val[domain]);
|
|
204
|
+
if (i < domains.length - 1) {
|
|
205
|
+
result += ",";
|
|
206
|
+
}
|
|
207
|
+
result += "\n";
|
|
208
|
+
});
|
|
209
|
+
result += "}";
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function formatDomain(domainName, domainValue) {
|
|
214
|
+
const indent = " ";
|
|
215
|
+
let result = `${indent}'${domainName}': {\n`;
|
|
216
|
+
Object.keys(domainValue).forEach((path, i, paths) => {
|
|
217
|
+
result += formatPath(path, domainValue[path]);
|
|
218
|
+
if (i < paths.length - 1) {
|
|
219
|
+
result += ",";
|
|
220
|
+
}
|
|
221
|
+
result += "\n";
|
|
222
|
+
});
|
|
223
|
+
result += `${indent}}`;
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function formatPath(pathName, pathValue) {
|
|
228
|
+
const indent = " ";
|
|
229
|
+
let result = `${indent}'${pathName}': {\n`;
|
|
230
|
+
Object.keys(pathValue).forEach((cookieName, i, cookieNames) => {
|
|
231
|
+
const cookie = pathValue[cookieName];
|
|
232
|
+
result += ` ${cookieName}: ${cookie.inspect()}`;
|
|
233
|
+
if (i < cookieNames.length - 1) {
|
|
234
|
+
result += ",";
|
|
235
|
+
}
|
|
236
|
+
result += "\n";
|
|
237
|
+
});
|
|
238
|
+
result += `${indent}}`;
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
exports.inspectFallback = inspectFallback;
|
package/lib/permuteDomain.js
CHANGED
|
@@ -33,21 +33,11 @@ const pubsuffix = require("./pubsuffix-psl");
|
|
|
33
33
|
|
|
34
34
|
// Gives the permutation of all possible domainMatch()es of a given domain. The
|
|
35
35
|
// array is in shortest-to-longest order. Handy for indexing.
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
function permuteDomain(domain, allowSpecialUseDomain) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (SPECIAL_USE_DOMAINS.includes(domainParts[domainParts.length - 1])) {
|
|
42
|
-
pubSuf = `${domainParts[domainParts.length - 2]}.${
|
|
43
|
-
domainParts[domainParts.length - 1]
|
|
44
|
-
}`;
|
|
45
|
-
} else {
|
|
46
|
-
pubSuf = pubsuffix.getPublicSuffix(domain);
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
pubSuf = pubsuffix.getPublicSuffix(domain);
|
|
50
|
-
}
|
|
38
|
+
const pubSuf = pubsuffix.getPublicSuffix(domain, {
|
|
39
|
+
allowSpecialUseDomain: allowSpecialUseDomain
|
|
40
|
+
});
|
|
51
41
|
|
|
52
42
|
if (!pubSuf) {
|
|
53
43
|
return null;
|
|
@@ -56,6 +46,11 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
56
46
|
return [domain];
|
|
57
47
|
}
|
|
58
48
|
|
|
49
|
+
// Nuke trailing dot
|
|
50
|
+
if (domain.slice(-1) == ".") {
|
|
51
|
+
domain = domain.slice(0, -1);
|
|
52
|
+
}
|
|
53
|
+
|
|
59
54
|
const prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
|
|
60
55
|
const parts = prefix.split(".").reverse();
|
|
61
56
|
let cur = pubSuf;
|
package/lib/pubsuffix-psl.js
CHANGED
|
@@ -31,7 +31,42 @@
|
|
|
31
31
|
"use strict";
|
|
32
32
|
const psl = require("psl");
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
// RFC 6761
|
|
35
|
+
const SPECIAL_USE_DOMAINS = [
|
|
36
|
+
"local",
|
|
37
|
+
"example",
|
|
38
|
+
"invalid",
|
|
39
|
+
"localhost",
|
|
40
|
+
"test"
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const SPECIAL_TREATMENT_DOMAINS = ["localhost", "invalid"];
|
|
44
|
+
|
|
45
|
+
function getPublicSuffix(domain, options = {}) {
|
|
46
|
+
const domainParts = domain.split(".");
|
|
47
|
+
const topLevelDomain = domainParts[domainParts.length - 1];
|
|
48
|
+
const allowSpecialUseDomain = !!options.allowSpecialUseDomain;
|
|
49
|
+
const ignoreError = !!options.ignoreError;
|
|
50
|
+
|
|
51
|
+
if (allowSpecialUseDomain && SPECIAL_USE_DOMAINS.includes(topLevelDomain)) {
|
|
52
|
+
if (domainParts.length > 1) {
|
|
53
|
+
const secondLevelDomain = domainParts[domainParts.length - 2];
|
|
54
|
+
// In aforementioned example, the eTLD/pubSuf will be apple.localhost
|
|
55
|
+
return `${secondLevelDomain}.${topLevelDomain}`;
|
|
56
|
+
} else if (SPECIAL_TREATMENT_DOMAINS.includes(topLevelDomain)) {
|
|
57
|
+
// For a single word special use domain, e.g. 'localhost' or 'invalid', per RFC 6761,
|
|
58
|
+
// "Application software MAY recognize {localhost/invalid} names as special, or
|
|
59
|
+
// MAY pass them to name resolution APIs as they would for other domain names."
|
|
60
|
+
return `${topLevelDomain}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!ignoreError && SPECIAL_USE_DOMAINS.includes(topLevelDomain)) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`Cookie has domain set to the public suffix "${topLevelDomain}" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain:true, rejectPublicSuffixes: false}.`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
35
70
|
return psl.get(domain);
|
|
36
71
|
}
|
|
37
72
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function requireUtil() {
|
|
2
|
+
try {
|
|
3
|
+
// eslint-disable-next-line no-restricted-modules
|
|
4
|
+
return require("util");
|
|
5
|
+
} catch (e) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// for v10.12.0+
|
|
11
|
+
function lookupCustomInspectSymbol() {
|
|
12
|
+
return Symbol.for("nodejs.util.inspect.custom");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// for older node environments
|
|
16
|
+
function tryReadingCustomSymbolFromUtilInspect(options) {
|
|
17
|
+
const _requireUtil = options.requireUtil || requireUtil;
|
|
18
|
+
const util = _requireUtil();
|
|
19
|
+
return util ? util.inspect.custom : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.getUtilInspect = function getUtilInspect(fallback, options = {}) {
|
|
23
|
+
const _requireUtil = options.requireUtil || requireUtil;
|
|
24
|
+
const util = _requireUtil();
|
|
25
|
+
return function inspect(value, showHidden, depth) {
|
|
26
|
+
return util ? util.inspect(value, showHidden, depth) : fallback(value);
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
exports.getCustomInspectSymbol = function getCustomInspectSymbol(options = {}) {
|
|
31
|
+
const _lookupCustomInspectSymbol =
|
|
32
|
+
options.lookupCustomInspectSymbol || lookupCustomInspectSymbol;
|
|
33
|
+
|
|
34
|
+
// get custom inspect symbol for node environments
|
|
35
|
+
return (
|
|
36
|
+
_lookupCustomInspectSymbol() ||
|
|
37
|
+
tryReadingCustomSymbolFromUtilInspect(options)
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* ************************************************************************************
|
|
2
|
+
Extracted from check-types.js
|
|
3
|
+
https://gitlab.com/philbooth/check-types.js
|
|
4
|
+
|
|
5
|
+
MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Phil Booth
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
************************************************************************************ */
|
|
28
|
+
"use strict";
|
|
29
|
+
|
|
30
|
+
/* Validation functions copied from check-types package - https://www.npmjs.com/package/check-types */
|
|
31
|
+
function isFunction(data) {
|
|
32
|
+
return typeof data === "function";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isNonEmptyString(data) {
|
|
36
|
+
return isString(data) && data !== "";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isDate(data) {
|
|
40
|
+
return isInstanceStrict(data, Date) && isInteger(data.getTime());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isEmptyString(data) {
|
|
44
|
+
return data === "" || (data instanceof String && data.toString() === "");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isString(data) {
|
|
48
|
+
return typeof data === "string" || data instanceof String;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isObject(data) {
|
|
52
|
+
return toString.call(data) === "[object Object]";
|
|
53
|
+
}
|
|
54
|
+
function isInstanceStrict(data, prototype) {
|
|
55
|
+
try {
|
|
56
|
+
return data instanceof prototype;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isInteger(data) {
|
|
63
|
+
return typeof data === "number" && data % 1 === 0;
|
|
64
|
+
}
|
|
65
|
+
/* End validation functions */
|
|
66
|
+
|
|
67
|
+
function validate(bool, cb, options) {
|
|
68
|
+
if (!isFunction(cb)) {
|
|
69
|
+
options = cb;
|
|
70
|
+
cb = null;
|
|
71
|
+
}
|
|
72
|
+
if (!isObject(options)) options = { Error: "Failed Check" };
|
|
73
|
+
if (!bool) {
|
|
74
|
+
if (cb) {
|
|
75
|
+
cb(new ParameterError(options));
|
|
76
|
+
} else {
|
|
77
|
+
throw new ParameterError(options);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class ParameterError extends Error {
|
|
83
|
+
constructor(...params) {
|
|
84
|
+
super(...params);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
exports.ParameterError = ParameterError;
|
|
89
|
+
exports.isFunction = isFunction;
|
|
90
|
+
exports.isNonEmptyString = isNonEmptyString;
|
|
91
|
+
exports.isDate = isDate;
|
|
92
|
+
exports.isEmptyString = isEmptyString;
|
|
93
|
+
exports.isString = isString;
|
|
94
|
+
exports.isObject = isObject;
|
|
95
|
+
exports.validate = validate;
|
package/lib/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by genversion
|
|
2
|
-
module.exports = '4.
|
|
2
|
+
module.exports = '4.1.2'
|