source: frontend/node_modules/cookie/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 8.0 KB
RevLine 
[9af201e]1/*!
2 * cookie
3 * Copyright(c) 2012-2014 Roman Shtylman
4 * Copyright(c) 2015 Douglas Christopher Wilson
5 * MIT Licensed
6 */
7
8'use strict';
9
10/**
11 * Module exports.
12 * @public
13 */
14
15exports.parse = parse;
16exports.serialize = serialize;
17
18/**
19 * Module variables.
20 * @private
21 */
22
23var __toString = Object.prototype.toString
24var __hasOwnProperty = Object.prototype.hasOwnProperty
25
26/**
27 * RegExp to match cookie-name in RFC 6265 sec 4.1.1
28 * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
29 * which has been replaced by the token definition in RFC 7230 appendix B.
30 *
31 * cookie-name = token
32 * token = 1*tchar
33 * tchar = "!" / "#" / "$" / "%" / "&" / "'" /
34 * "*" / "+" / "-" / "." / "^" / "_" /
35 * "`" / "|" / "~" / DIGIT / ALPHA
36 */
37
38var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
39
40/**
41 * RegExp to match cookie-value in RFC 6265 sec 4.1.1
42 *
43 * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
44 * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
45 * ; US-ASCII characters excluding CTLs,
46 * ; whitespace DQUOTE, comma, semicolon,
47 * ; and backslash
48 */
49
50var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
51
52/**
53 * RegExp to match domain-value in RFC 6265 sec 4.1.1
54 *
55 * domain-value = <subdomain>
56 * ; defined in [RFC1034], Section 3.5, as
57 * ; enhanced by [RFC1123], Section 2.1
58 * <subdomain> = <label> | <subdomain> "." <label>
59 * <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ]
60 * Labels must be 63 characters or less.
61 * 'let-dig' not 'letter' in the first char, per RFC1123
62 * <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
63 * <let-dig-hyp> = <let-dig> | "-"
64 * <let-dig> = <letter> | <digit>
65 * <letter> = any one of the 52 alphabetic characters A through Z in
66 * upper case and a through z in lower case
67 * <digit> = any one of the ten digits 0 through 9
68 *
69 * Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
70 *
71 * > (Note that a leading %x2E ("."), if present, is ignored even though that
72 * character is not permitted, but a trailing %x2E ("."), if present, will
73 * cause the user agent to ignore the attribute.)
74 */
75
76var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
77
78/**
79 * RegExp to match path-value in RFC 6265 sec 4.1.1
80 *
81 * path-value = <any CHAR except CTLs or ";">
82 * CHAR = %x01-7F
83 * ; defined in RFC 5234 appendix B.1
84 */
85
86var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
87
88/**
89 * Parse a cookie header.
90 *
91 * Parse the given cookie header string into an object
92 * The object has the various cookies as keys(names) => values
93 *
94 * @param {string} str
95 * @param {object} [opt]
96 * @return {object}
97 * @public
98 */
99
100function parse(str, opt) {
101 if (typeof str !== 'string') {
102 throw new TypeError('argument str must be a string');
103 }
104
105 var obj = {};
106 var len = str.length;
107 // RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
108 if (len < 2) return obj;
109
110 var dec = (opt && opt.decode) || decode;
111 var index = 0;
112 var eqIdx = 0;
113 var endIdx = 0;
114
115 do {
116 eqIdx = str.indexOf('=', index);
117 if (eqIdx === -1) break; // No more cookie pairs.
118
119 endIdx = str.indexOf(';', index);
120
121 if (endIdx === -1) {
122 endIdx = len;
123 } else if (eqIdx > endIdx) {
124 // backtrack on prior semicolon
125 index = str.lastIndexOf(';', eqIdx - 1) + 1;
126 continue;
127 }
128
129 var keyStartIdx = startIndex(str, index, eqIdx);
130 var keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
131 var key = str.slice(keyStartIdx, keyEndIdx);
132
133 // only assign once
134 if (!__hasOwnProperty.call(obj, key)) {
135 var valStartIdx = startIndex(str, eqIdx + 1, endIdx);
136 var valEndIdx = endIndex(str, endIdx, valStartIdx);
137
138 if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) {
139 valStartIdx++;
140 valEndIdx--;
141 }
142
143 var val = str.slice(valStartIdx, valEndIdx);
144 obj[key] = tryDecode(val, dec);
145 }
146
147 index = endIdx + 1
148 } while (index < len);
149
150 return obj;
151}
152
153function startIndex(str, index, max) {
154 do {
155 var code = str.charCodeAt(index);
156 if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index;
157 } while (++index < max);
158 return max;
159}
160
161function endIndex(str, index, min) {
162 while (index > min) {
163 var code = str.charCodeAt(--index);
164 if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index + 1;
165 }
166 return min;
167}
168
169/**
170 * Serialize data into a cookie header.
171 *
172 * Serialize a name value pair into a cookie string suitable for
173 * http headers. An optional options object specifies cookie parameters.
174 *
175 * serialize('foo', 'bar', { httpOnly: true })
176 * => "foo=bar; httpOnly"
177 *
178 * @param {string} name
179 * @param {string} val
180 * @param {object} [opt]
181 * @return {string}
182 * @public
183 */
184
185function serialize(name, val, opt) {
186 var enc = (opt && opt.encode) || encodeURIComponent;
187
188 if (typeof enc !== 'function') {
189 throw new TypeError('option encode is invalid');
190 }
191
192 if (!cookieNameRegExp.test(name)) {
193 throw new TypeError('argument name is invalid');
194 }
195
196 var value = enc(val);
197
198 if (!cookieValueRegExp.test(value)) {
199 throw new TypeError('argument val is invalid');
200 }
201
202 var str = name + '=' + value;
203 if (!opt) return str;
204
205 if (null != opt.maxAge) {
206 var maxAge = Math.floor(opt.maxAge);
207
208 if (!isFinite(maxAge)) {
209 throw new TypeError('option maxAge is invalid')
210 }
211
212 str += '; Max-Age=' + maxAge;
213 }
214
215 if (opt.domain) {
216 if (!domainValueRegExp.test(opt.domain)) {
217 throw new TypeError('option domain is invalid');
218 }
219
220 str += '; Domain=' + opt.domain;
221 }
222
223 if (opt.path) {
224 if (!pathValueRegExp.test(opt.path)) {
225 throw new TypeError('option path is invalid');
226 }
227
228 str += '; Path=' + opt.path;
229 }
230
231 if (opt.expires) {
232 var expires = opt.expires
233
234 if (!isDate(expires) || isNaN(expires.valueOf())) {
235 throw new TypeError('option expires is invalid');
236 }
237
238 str += '; Expires=' + expires.toUTCString()
239 }
240
241 if (opt.httpOnly) {
242 str += '; HttpOnly';
243 }
244
245 if (opt.secure) {
246 str += '; Secure';
247 }
248
249 if (opt.partitioned) {
250 str += '; Partitioned'
251 }
252
253 if (opt.priority) {
254 var priority = typeof opt.priority === 'string'
255 ? opt.priority.toLowerCase() : opt.priority;
256
257 switch (priority) {
258 case 'low':
259 str += '; Priority=Low'
260 break
261 case 'medium':
262 str += '; Priority=Medium'
263 break
264 case 'high':
265 str += '; Priority=High'
266 break
267 default:
268 throw new TypeError('option priority is invalid')
269 }
270 }
271
272 if (opt.sameSite) {
273 var sameSite = typeof opt.sameSite === 'string'
274 ? opt.sameSite.toLowerCase() : opt.sameSite;
275
276 switch (sameSite) {
277 case true:
278 str += '; SameSite=Strict';
279 break;
280 case 'lax':
281 str += '; SameSite=Lax';
282 break;
283 case 'strict':
284 str += '; SameSite=Strict';
285 break;
286 case 'none':
287 str += '; SameSite=None';
288 break;
289 default:
290 throw new TypeError('option sameSite is invalid');
291 }
292 }
293
294 return str;
295}
296
297/**
298 * URL-decode string value. Optimized to skip native call when no %.
299 *
300 * @param {string} str
301 * @returns {string}
302 */
303
304function decode (str) {
305 return str.indexOf('%') !== -1
306 ? decodeURIComponent(str)
307 : str
308}
309
310/**
311 * Determine if value is a Date.
312 *
313 * @param {*} val
314 * @private
315 */
316
317function isDate (val) {
318 return __toString.call(val) === '[object Date]';
319}
320
321/**
322 * Try decoding a string using a decoding function.
323 *
324 * @param {string} str
325 * @param {function} decode
326 * @private
327 */
328
329function tryDecode(str, decode) {
330 try {
331 return decode(str);
332 } catch (e) {
333 return str;
334 }
335}
Note: See TracBrowser for help on using the repository browser.