tough-cookie 2.3.3 → 2.3.4
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 +1 -1
- package/lib/cookie.js +174 -89
- package/lib/pubsuffix.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,7 +134,7 @@ else
|
|
|
134
134
|
cookies = [Cookie.parse(res.headers['set-cookie'])];
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
_Note:_ in version 2.3.3, tough-cookie limited the number of spaces before the `=` to 256 characters. This limitation has since been removed.
|
|
138
138
|
See [Issue 92](https://github.com/salesforce/tough-cookie/issues/92)
|
|
139
139
|
|
|
140
140
|
### Properties
|
package/lib/cookie.js
CHANGED
|
@@ -44,37 +44,24 @@ try {
|
|
|
44
44
|
console.warn("cookie: can't load punycode; won't use punycode for domain normalization");
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
|
|
48
|
-
|
|
49
47
|
// From RFC6265 S4.1.1
|
|
50
48
|
// note that it excludes \x3B ";"
|
|
51
|
-
var
|
|
52
|
-
var COOKIE_OCTETS = new RegExp('^'+COOKIE_OCTET.source+'+$');
|
|
49
|
+
var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
|
|
53
50
|
|
|
54
51
|
var CONTROL_CHARS = /[\x00-\x1F]/;
|
|
55
52
|
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
// https://github.com/
|
|
59
|
-
|
|
60
|
-
// Double quotes are part of the value (see: S4.1.1).
|
|
61
|
-
// '\r', '\n' and '\0' should be treated as a terminator in the "relaxed" mode
|
|
62
|
-
// (see: https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60)
|
|
63
|
-
// '=' and ';' are attribute/values separators
|
|
64
|
-
// (see: https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L64)
|
|
65
|
-
var COOKIE_PAIR = /^(([^=;]+))\s{0,256}=\s*([^\n\r\0]*)/;
|
|
66
|
-
|
|
67
|
-
// Used to parse non-RFC-compliant cookies like '=abc' when given the `loose`
|
|
68
|
-
// option in Cookie.parse:
|
|
69
|
-
var LOOSE_COOKIE_PAIR = /^((?:=)?([^=;]*)\s{0,256}=\s*)?([^\n\r\0]*)/;
|
|
53
|
+
// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
|
|
54
|
+
// the "relaxed" mode, see:
|
|
55
|
+
// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
|
|
56
|
+
var TERMINATORS = ['\n', '\r', '\0'];
|
|
70
57
|
|
|
71
58
|
// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
|
|
72
59
|
// Note ';' is \x3B
|
|
73
60
|
var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var
|
|
62
|
+
// date-time parsing constants (RFC6265 S5.1.1)
|
|
63
|
+
|
|
64
|
+
var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
|
|
78
65
|
|
|
79
66
|
var MONTH_TO_NUM = {
|
|
80
67
|
jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
|
|
@@ -87,13 +74,80 @@ var NUM_TO_DAY = [
|
|
|
87
74
|
'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
|
|
88
75
|
];
|
|
89
76
|
|
|
90
|
-
var YEAR = /^(\d{2}|\d{4})$/; // 2 to 4 digits
|
|
91
|
-
|
|
92
77
|
var MAX_TIME = 2147483647000; // 31-bit max
|
|
93
78
|
var MIN_TIME = 0; // 31-bit min
|
|
94
79
|
|
|
80
|
+
/*
|
|
81
|
+
* Parses a Natural number (i.e., non-negative integer) with either the
|
|
82
|
+
* <min>*<max>DIGIT ( non-digit *OCTET )
|
|
83
|
+
* or
|
|
84
|
+
* <min>*<max>DIGIT
|
|
85
|
+
* grammar (RFC6265 S5.1.1).
|
|
86
|
+
*
|
|
87
|
+
* The "trailingOK" boolean controls if the grammar accepts a
|
|
88
|
+
* "( non-digit *OCTET )" trailer.
|
|
89
|
+
*/
|
|
90
|
+
function parseDigits(token, minDigits, maxDigits, trailingOK) {
|
|
91
|
+
var count = 0;
|
|
92
|
+
while (count < token.length) {
|
|
93
|
+
var c = token.charCodeAt(count);
|
|
94
|
+
// "non-digit = %x00-2F / %x3A-FF"
|
|
95
|
+
if (c <= 0x2F || c >= 0x3A) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
count++;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// constrain to a minimum and maximum number of digits.
|
|
102
|
+
if (count < minDigits || count > maxDigits) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!trailingOK && count != token.length) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
95
109
|
|
|
96
|
-
|
|
110
|
+
return parseInt(token.substr(0,count), 10);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseTime(token) {
|
|
114
|
+
var parts = token.split(':');
|
|
115
|
+
var result = [0,0,0];
|
|
116
|
+
|
|
117
|
+
/* RF6256 S5.1.1:
|
|
118
|
+
* time = hms-time ( non-digit *OCTET )
|
|
119
|
+
* hms-time = time-field ":" time-field ":" time-field
|
|
120
|
+
* time-field = 1*2DIGIT
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
if (parts.length !== 3) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (var i = 0; i < 3; i++) {
|
|
128
|
+
// "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
|
|
129
|
+
// followed by "( non-digit *OCTET )" so therefore the last time-field can
|
|
130
|
+
// have a trailer
|
|
131
|
+
var trailingOK = (i == 2);
|
|
132
|
+
var num = parseDigits(parts[i], 1, 2, trailingOK);
|
|
133
|
+
if (num === null) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
result[i] = num;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function parseMonth(token) {
|
|
143
|
+
token = String(token).substr(0,3).toLowerCase();
|
|
144
|
+
var num = MONTH_TO_NUM[token];
|
|
145
|
+
return num >= 0 ? num : null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
* RFC6265 S5.1.1 date parser (see RFC for full grammar)
|
|
150
|
+
*/
|
|
97
151
|
function parseDate(str) {
|
|
98
152
|
if (!str) {
|
|
99
153
|
return;
|
|
@@ -109,9 +163,9 @@ function parseDate(str) {
|
|
|
109
163
|
}
|
|
110
164
|
|
|
111
165
|
var hour = null;
|
|
112
|
-
var
|
|
113
|
-
var
|
|
114
|
-
var
|
|
166
|
+
var minute = null;
|
|
167
|
+
var second = null;
|
|
168
|
+
var dayOfMonth = null;
|
|
115
169
|
var month = null;
|
|
116
170
|
var year = null;
|
|
117
171
|
|
|
@@ -129,22 +183,12 @@ function parseDate(str) {
|
|
|
129
183
|
* the date-token, respectively. Skip the remaining sub-steps and continue
|
|
130
184
|
* to the next date-token.
|
|
131
185
|
*/
|
|
132
|
-
if (
|
|
133
|
-
result =
|
|
186
|
+
if (second === null) {
|
|
187
|
+
result = parseTime(token);
|
|
134
188
|
if (result) {
|
|
135
|
-
hour =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/* RFC6265 S5.1.1.5:
|
|
139
|
-
* [fail if]
|
|
140
|
-
* * the hour-value is greater than 23,
|
|
141
|
-
* * the minute-value is greater than 59, or
|
|
142
|
-
* * the second-value is greater than 59.
|
|
143
|
-
*/
|
|
144
|
-
if(hour > 23 || minutes > 59 || seconds > 59) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
189
|
+
hour = result[0];
|
|
190
|
+
minute = result[1];
|
|
191
|
+
second = result[2];
|
|
148
192
|
continue;
|
|
149
193
|
}
|
|
150
194
|
}
|
|
@@ -154,16 +198,11 @@ function parseDate(str) {
|
|
|
154
198
|
* the day-of-month-value to the number denoted by the date-token. Skip
|
|
155
199
|
* the remaining sub-steps and continue to the next date-token.
|
|
156
200
|
*/
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* [fail if] the day-of-month-value is less than 1 or greater than 31
|
|
163
|
-
*/
|
|
164
|
-
if(day < 1 || day > 31) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
201
|
+
if (dayOfMonth === null) {
|
|
202
|
+
// "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
|
|
203
|
+
result = parseDigits(token, 1, 2, true);
|
|
204
|
+
if (result !== null) {
|
|
205
|
+
dayOfMonth = result;
|
|
167
206
|
continue;
|
|
168
207
|
}
|
|
169
208
|
}
|
|
@@ -174,47 +213,63 @@ function parseDate(str) {
|
|
|
174
213
|
* continue to the next date-token.
|
|
175
214
|
*/
|
|
176
215
|
if (month === null) {
|
|
177
|
-
result =
|
|
178
|
-
if (result) {
|
|
179
|
-
month =
|
|
216
|
+
result = parseMonth(token);
|
|
217
|
+
if (result !== null) {
|
|
218
|
+
month = result;
|
|
180
219
|
continue;
|
|
181
220
|
}
|
|
182
221
|
}
|
|
183
222
|
|
|
184
|
-
/* 2.4. If the found-year flag is not set and the date-token matches the
|
|
185
|
-
* production, set the found-year flag and set the year-value to the
|
|
186
|
-
* denoted by the date-token. Skip the remaining sub-steps and
|
|
187
|
-
* the next date-token.
|
|
223
|
+
/* 2.4. If the found-year flag is not set and the date-token matches the
|
|
224
|
+
* year production, set the found-year flag and set the year-value to the
|
|
225
|
+
* number denoted by the date-token. Skip the remaining sub-steps and
|
|
226
|
+
* continue to the next date-token.
|
|
188
227
|
*/
|
|
189
228
|
if (year === null) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
229
|
+
// "year = 2*4DIGIT ( non-digit *OCTET )"
|
|
230
|
+
result = parseDigits(token, 2, 4, true);
|
|
231
|
+
if (result !== null) {
|
|
232
|
+
year = result;
|
|
193
233
|
/* From S5.1.1:
|
|
194
234
|
* 3. If the year-value is greater than or equal to 70 and less
|
|
195
235
|
* than or equal to 99, increment the year-value by 1900.
|
|
196
236
|
* 4. If the year-value is greater than or equal to 0 and less
|
|
197
237
|
* than or equal to 69, increment the year-value by 2000.
|
|
198
238
|
*/
|
|
199
|
-
if (
|
|
239
|
+
if (year >= 70 && year <= 99) {
|
|
200
240
|
year += 1900;
|
|
201
|
-
} else if (
|
|
241
|
+
} else if (year >= 0 && year <= 69) {
|
|
202
242
|
year += 2000;
|
|
203
243
|
}
|
|
204
|
-
|
|
205
|
-
if (year < 1601) {
|
|
206
|
-
return; // 5. ... the year-value is less than 1601
|
|
207
|
-
}
|
|
208
244
|
}
|
|
209
245
|
}
|
|
210
246
|
}
|
|
211
247
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
248
|
+
/* RFC 6265 S5.1.1
|
|
249
|
+
* "5. Abort these steps and fail to parse the cookie-date if:
|
|
250
|
+
* * at least one of the found-day-of-month, found-month, found-
|
|
251
|
+
* year, or found-time flags is not set,
|
|
252
|
+
* * the day-of-month-value is less than 1 or greater than 31,
|
|
253
|
+
* * the year-value is less than 1601,
|
|
254
|
+
* * the hour-value is greater than 23,
|
|
255
|
+
* * the minute-value is greater than 59, or
|
|
256
|
+
* * the second-value is greater than 59.
|
|
257
|
+
* (Note that leap seconds cannot be represented in this syntax.)"
|
|
258
|
+
*
|
|
259
|
+
* So, in order as above:
|
|
260
|
+
*/
|
|
261
|
+
if (
|
|
262
|
+
dayOfMonth === null || month === null || year === null || second === null ||
|
|
263
|
+
dayOfMonth < 1 || dayOfMonth > 31 ||
|
|
264
|
+
year < 1601 ||
|
|
265
|
+
hour > 23 ||
|
|
266
|
+
minute > 59 ||
|
|
267
|
+
second > 59
|
|
268
|
+
) {
|
|
269
|
+
return;
|
|
215
270
|
}
|
|
216
271
|
|
|
217
|
-
return new Date(Date.UTC(year, month,
|
|
272
|
+
return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
|
|
218
273
|
}
|
|
219
274
|
|
|
220
275
|
function formatDate(date) {
|
|
@@ -321,32 +376,62 @@ function defaultPath(path) {
|
|
|
321
376
|
return path.slice(0, rightSlash);
|
|
322
377
|
}
|
|
323
378
|
|
|
379
|
+
function trimTerminator(str) {
|
|
380
|
+
for (var t = 0; t < TERMINATORS.length; t++) {
|
|
381
|
+
var terminatorIdx = str.indexOf(TERMINATORS[t]);
|
|
382
|
+
if (terminatorIdx !== -1) {
|
|
383
|
+
str = str.substr(0,terminatorIdx);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
324
386
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
387
|
+
return str;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function parseCookiePair(cookiePair, looseMode) {
|
|
391
|
+
cookiePair = trimTerminator(cookiePair);
|
|
392
|
+
|
|
393
|
+
var firstEq = cookiePair.indexOf('=');
|
|
394
|
+
if (looseMode) {
|
|
395
|
+
if (firstEq === 0) { // '=' is immediately at start
|
|
396
|
+
cookiePair = cookiePair.substr(1);
|
|
397
|
+
firstEq = cookiePair.indexOf('='); // might still need to split on '='
|
|
398
|
+
}
|
|
399
|
+
} else { // non-loose mode
|
|
400
|
+
if (firstEq <= 0) { // no '=' or is at start
|
|
401
|
+
return; // needs to have non-empty "cookie-name"
|
|
402
|
+
}
|
|
328
403
|
}
|
|
329
|
-
str = str.trim();
|
|
330
404
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
405
|
+
var cookieName, cookieValue;
|
|
406
|
+
if (firstEq <= 0) {
|
|
407
|
+
cookieName = "";
|
|
408
|
+
cookieValue = cookiePair.trim();
|
|
409
|
+
} else {
|
|
410
|
+
cookieName = cookiePair.substr(0, firstEq).trim();
|
|
411
|
+
cookieValue = cookiePair.substr(firstEq+1).trim();
|
|
412
|
+
}
|
|
335
413
|
|
|
336
|
-
|
|
337
|
-
// constraints as well as trimming any whitespace.
|
|
338
|
-
if (!result) {
|
|
414
|
+
if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
|
|
339
415
|
return;
|
|
340
416
|
}
|
|
341
417
|
|
|
342
418
|
var c = new Cookie();
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
419
|
+
c.key = cookieName;
|
|
420
|
+
c.value = cookieValue;
|
|
421
|
+
return c;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function parse(str, options) {
|
|
425
|
+
if (!options || typeof options !== 'object') {
|
|
426
|
+
options = {};
|
|
347
427
|
}
|
|
348
|
-
|
|
349
|
-
|
|
428
|
+
str = str.trim();
|
|
429
|
+
|
|
430
|
+
// We use a regex to parse the "name-value-pair" part of S5.2
|
|
431
|
+
var firstSemi = str.indexOf(';'); // S5.2 step 1
|
|
432
|
+
var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
|
|
433
|
+
var c = parseCookiePair(cookiePair, !!options.loose);
|
|
434
|
+
if (!c) {
|
|
350
435
|
return;
|
|
351
436
|
}
|
|
352
437
|
|