tough-cookie 4.0.0 → 4.1.0
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 +105 -23
- package/lib/memstore.js +56 -4
- package/lib/permuteDomain.js +9 -14
- package/lib/pubsuffix-psl.js +33 -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,6 +1096,7 @@ 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
1102
|
this.allowSpecialUseDomain = !!options.allowSpecialUseDomain;
|
|
@@ -1076,13 +1113,31 @@ class CookieJar {
|
|
|
1076
1113
|
}
|
|
1077
1114
|
|
|
1078
1115
|
setCookie(cookie, url, options, cb) {
|
|
1116
|
+
validators.validate(validators.isNonEmptyString(url), cb, options);
|
|
1079
1117
|
let err;
|
|
1118
|
+
|
|
1119
|
+
if (validators.isFunction(url)) {
|
|
1120
|
+
cb = url;
|
|
1121
|
+
return cb(new Error("No URL was specified"));
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1080
1124
|
const context = getCookieContext(url);
|
|
1081
|
-
if (
|
|
1125
|
+
if (validators.isFunction(options)) {
|
|
1082
1126
|
cb = options;
|
|
1083
1127
|
options = {};
|
|
1084
1128
|
}
|
|
1085
1129
|
|
|
1130
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1131
|
+
|
|
1132
|
+
if (
|
|
1133
|
+
!validators.isNonEmptyString(cookie) &&
|
|
1134
|
+
!validators.isObject(cookie) &&
|
|
1135
|
+
cookie instanceof String &&
|
|
1136
|
+
cookie.length == 0
|
|
1137
|
+
) {
|
|
1138
|
+
return cb(null);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1086
1141
|
const host = canonicalDomain(context.hostname);
|
|
1087
1142
|
const loose = options.loose || this.enableLooseMode;
|
|
1088
1143
|
|
|
@@ -1119,8 +1174,11 @@ class CookieJar {
|
|
|
1119
1174
|
|
|
1120
1175
|
// S5.3 step 5: public suffixes
|
|
1121
1176
|
if (this.rejectPublicSuffixes && cookie.domain) {
|
|
1122
|
-
const suffix = pubsuffix.getPublicSuffix(cookie.cdomain()
|
|
1123
|
-
|
|
1177
|
+
const suffix = pubsuffix.getPublicSuffix(cookie.cdomain(), {
|
|
1178
|
+
allowSpecialUseDomain: this.allowSpecialUseDomain,
|
|
1179
|
+
ignoreError: options.ignoreError
|
|
1180
|
+
});
|
|
1181
|
+
if (suffix == null && !IP_V6_REGEX_OBJECT.test(cookie.domain)) {
|
|
1124
1182
|
// e.g. "com"
|
|
1125
1183
|
err = new Error("Cookie has domain set to a public suffix");
|
|
1126
1184
|
return cb(options.ignoreError ? null : err);
|
|
@@ -1163,7 +1221,11 @@ class CookieJar {
|
|
|
1163
1221
|
}
|
|
1164
1222
|
|
|
1165
1223
|
// 6252bis-02 S5.4 Step 13 & 14:
|
|
1166
|
-
if (
|
|
1224
|
+
if (
|
|
1225
|
+
cookie.sameSite !== "none" &&
|
|
1226
|
+
cookie.sameSite !== undefined &&
|
|
1227
|
+
sameSiteContext
|
|
1228
|
+
) {
|
|
1167
1229
|
// "If the cookie's "same-site-flag" is not "None", and the cookie
|
|
1168
1230
|
// is being set from a context whose "site for cookies" is not an
|
|
1169
1231
|
// exact match for request-uri's host's registered domain, then
|
|
@@ -1249,11 +1311,14 @@ class CookieJar {
|
|
|
1249
1311
|
|
|
1250
1312
|
// RFC6365 S5.4
|
|
1251
1313
|
getCookies(url, options, cb) {
|
|
1314
|
+
validators.validate(validators.isNonEmptyString(url), cb, url);
|
|
1252
1315
|
const context = getCookieContext(url);
|
|
1253
|
-
if (
|
|
1316
|
+
if (validators.isFunction(options)) {
|
|
1254
1317
|
cb = options;
|
|
1255
1318
|
options = {};
|
|
1256
1319
|
}
|
|
1320
|
+
validators.validate(validators.isObject(options), cb, options);
|
|
1321
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1257
1322
|
|
|
1258
1323
|
const host = canonicalDomain(context.hostname);
|
|
1259
1324
|
const path = context.pathname || "/";
|
|
@@ -1369,6 +1434,7 @@ class CookieJar {
|
|
|
1369
1434
|
|
|
1370
1435
|
getCookieString(...args) {
|
|
1371
1436
|
const cb = args.pop();
|
|
1437
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1372
1438
|
const next = function(err, cookies) {
|
|
1373
1439
|
if (err) {
|
|
1374
1440
|
cb(err);
|
|
@@ -1388,6 +1454,7 @@ class CookieJar {
|
|
|
1388
1454
|
|
|
1389
1455
|
getSetCookieStrings(...args) {
|
|
1390
1456
|
const cb = args.pop();
|
|
1457
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1391
1458
|
const next = function(err, cookies) {
|
|
1392
1459
|
if (err) {
|
|
1393
1460
|
cb(err);
|
|
@@ -1405,8 +1472,9 @@ class CookieJar {
|
|
|
1405
1472
|
}
|
|
1406
1473
|
|
|
1407
1474
|
serialize(cb) {
|
|
1475
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1408
1476
|
let type = this.store.constructor.name;
|
|
1409
|
-
if (type
|
|
1477
|
+
if (validators.isObject(type)) {
|
|
1410
1478
|
type = null;
|
|
1411
1479
|
}
|
|
1412
1480
|
|
|
@@ -1422,6 +1490,9 @@ class CookieJar {
|
|
|
1422
1490
|
|
|
1423
1491
|
// CookieJar configuration:
|
|
1424
1492
|
rejectPublicSuffixes: !!this.rejectPublicSuffixes,
|
|
1493
|
+
enableLooseMode: !!this.enableLooseMode,
|
|
1494
|
+
allowSpecialUseDomain: !!this.allowSpecialUseDomain,
|
|
1495
|
+
prefixSecurity: getNormalizedPrefixSecurity(this.prefixSecurity),
|
|
1425
1496
|
|
|
1426
1497
|
// this gets filled from getAllCookies:
|
|
1427
1498
|
cookies: []
|
|
@@ -1524,6 +1595,7 @@ class CookieJar {
|
|
|
1524
1595
|
}
|
|
1525
1596
|
|
|
1526
1597
|
removeAllCookies(cb) {
|
|
1598
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1527
1599
|
const store = this.store;
|
|
1528
1600
|
|
|
1529
1601
|
// Check that the store implements its own removeAllCookies(). The default
|
|
@@ -1577,6 +1649,7 @@ class CookieJar {
|
|
|
1577
1649
|
cb = store;
|
|
1578
1650
|
store = null;
|
|
1579
1651
|
}
|
|
1652
|
+
validators.validate(validators.isFunction(cb), cb);
|
|
1580
1653
|
|
|
1581
1654
|
let serialized;
|
|
1582
1655
|
if (typeof strOrObj === "string") {
|
|
@@ -1588,7 +1661,12 @@ class CookieJar {
|
|
|
1588
1661
|
serialized = strOrObj;
|
|
1589
1662
|
}
|
|
1590
1663
|
|
|
1591
|
-
const jar = new CookieJar(store,
|
|
1664
|
+
const jar = new CookieJar(store, {
|
|
1665
|
+
rejectPublicSuffixes: serialized.rejectPublicSuffixes,
|
|
1666
|
+
looseMode: serialized.enableLooseMode,
|
|
1667
|
+
allowSpecialUseDomain: serialized.allowSpecialUseDomain,
|
|
1668
|
+
prefixSecurity: serialized.prefixSecurity
|
|
1669
|
+
});
|
|
1592
1670
|
jar._importCookies(serialized, err => {
|
|
1593
1671
|
if (err) {
|
|
1594
1672
|
return cb(err);
|
|
@@ -1600,7 +1678,10 @@ class CookieJar {
|
|
|
1600
1678
|
static deserializeSync(strOrObj, store) {
|
|
1601
1679
|
const serialized =
|
|
1602
1680
|
typeof strOrObj === "string" ? JSON.parse(strOrObj) : strOrObj;
|
|
1603
|
-
const jar = new CookieJar(store,
|
|
1681
|
+
const jar = new CookieJar(store, {
|
|
1682
|
+
rejectPublicSuffixes: serialized.rejectPublicSuffixes,
|
|
1683
|
+
looseMode: serialized.enableLooseMode
|
|
1684
|
+
});
|
|
1604
1685
|
|
|
1605
1686
|
// catch this mistake early:
|
|
1606
1687
|
if (!jar.store.synchronous) {
|
|
@@ -1669,3 +1750,4 @@ exports.permuteDomain = require("./permuteDomain").permuteDomain;
|
|
|
1669
1750
|
exports.permutePath = permutePath;
|
|
1670
1751
|
exports.canonicalDomain = canonicalDomain;
|
|
1671
1752
|
exports.PrefixSecurityEnum = PrefixSecurityEnum;
|
|
1753
|
+
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
|
|
|
@@ -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,39 @@
|
|
|
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
|
+
function getPublicSuffix(domain, options = {}) {
|
|
44
|
+
const domainParts = domain.split(".");
|
|
45
|
+
const topLevelDomain = domainParts[domainParts.length - 1];
|
|
46
|
+
const allowSpecialUseDomain = !!options.allowSpecialUseDomain;
|
|
47
|
+
const ignoreError = !!options.ignoreError;
|
|
48
|
+
|
|
49
|
+
if (
|
|
50
|
+
allowSpecialUseDomain &&
|
|
51
|
+
domainParts.length > 1 &&
|
|
52
|
+
SPECIAL_USE_DOMAINS.includes(topLevelDomain)
|
|
53
|
+
) {
|
|
54
|
+
// If the right-most label in the name is a special-use domain (e.g. bananas.apple.localhost),
|
|
55
|
+
// then don't use PSL. This is because most special-use domains are not listed on PSL.
|
|
56
|
+
const secondLevelDomain = domainParts[domainParts.length - 2];
|
|
57
|
+
// In aforementioned example, the eTLD/pubSuf will be apple.localhost
|
|
58
|
+
return `${secondLevelDomain}.${topLevelDomain}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!ignoreError && SPECIAL_USE_DOMAINS.includes(topLevelDomain)) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`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}.`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
35
67
|
return psl.get(domain);
|
|
36
68
|
}
|
|
37
69
|
|
|
@@ -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.0'
|
package/package.json
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"RFC6265",
|
|
68
68
|
"RFC2965"
|
|
69
69
|
],
|
|
70
|
-
"version": "4.
|
|
70
|
+
"version": "4.1.0",
|
|
71
71
|
"homepage": "https://github.com/salesforce/tough-cookie",
|
|
72
72
|
"repository": {
|
|
73
73
|
"type": "git",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
],
|
|
83
83
|
"scripts": {
|
|
84
84
|
"version": "genversion lib/version.js && git add lib/version.js",
|
|
85
|
-
"test": "vows test/*_test.js",
|
|
85
|
+
"test": "vows test/*_test.js && npm run eslint",
|
|
86
86
|
"cover": "nyc --reporter=lcov --reporter=html vows test/*_test.js",
|
|
87
87
|
"eslint": "eslint --env node --ext .js .",
|
|
88
88
|
"prettier": "prettier '**/*.{json,ts,yaml,md}'",
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
"dependencies": {
|
|
105
105
|
"psl": "^1.1.33",
|
|
106
106
|
"punycode": "^2.1.1",
|
|
107
|
-
"universalify": "^0.
|
|
107
|
+
"universalify": "^0.2.0",
|
|
108
|
+
"url-parse": "^1.5.3"
|
|
108
109
|
}
|
|
109
110
|
}
|