Comparing version 0.6.0 to 0.7.0
132
index.js
@@ -26,12 +26,58 @@ /*! | ||
/** | ||
* RegExp to match field-content in RFC 7230 sec 3.2 | ||
* RegExp to match cookie-name in RFC 6265 sec 4.1.1 | ||
* This refers out to the obsoleted definition of token in RFC 2616 sec 2.2 | ||
* which has been replaced by the token definition in RFC 7230 appendix B. | ||
* | ||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] | ||
* field-vchar = VCHAR / obs-text | ||
* obs-text = %x80-FF | ||
* cookie-name = token | ||
* token = 1*tchar | ||
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / | ||
* "*" / "+" / "-" / "." / "^" / "_" / | ||
* "`" / "|" / "~" / DIGIT / ALPHA | ||
*/ | ||
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; | ||
var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; | ||
/** | ||
* RegExp to match cookie-value in RFC 6265 sec 4.1.1 | ||
* | ||
* cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) | ||
* cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E | ||
* ; US-ASCII characters excluding CTLs, | ||
* ; whitespace DQUOTE, comma, semicolon, | ||
* ; and backslash | ||
*/ | ||
var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/; | ||
/** | ||
* RegExp to match domain-value in RFC 6265 sec 4.1.1 | ||
* | ||
* domain-value = <subdomain> | ||
* ; defined in [RFC1034], Section 3.5, as | ||
* ; enhanced by [RFC1123], Section 2.1 | ||
* <subdomain> = <label> | <subdomain> "." <label> | ||
* <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ] | ||
* Labels must be 63 characters or less. | ||
* 'let-dig' not 'letter' in the first char, per RFC1123 | ||
* <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str> | ||
* <let-dig-hyp> = <let-dig> | "-" | ||
* <let-dig> = <letter> | <digit> | ||
* <letter> = any one of the 52 alphabetic characters A through Z in | ||
* upper case and a through z in lower case | ||
* <digit> = any one of the ten digits 0 through 9 | ||
*/ | ||
var domainValueRegExp = /^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; | ||
/** | ||
* RegExp to match path-value in RFC 6265 sec 4.1.1 | ||
* | ||
* path-value = <any CHAR except CTLs or ";"> | ||
* CHAR = %x01-7F | ||
* ; defined in RFC 5234 appendix B.1 | ||
*/ | ||
var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/; | ||
/** | ||
* Parse a cookie header. | ||
@@ -53,36 +99,46 @@ * | ||
var obj = {} | ||
var opt = options || {}; | ||
var dec = opt.decode || decode; | ||
var obj = {}; | ||
var len = str.length; | ||
// RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='. | ||
var max = len - 2; | ||
if (max < 0) return obj; | ||
var index = 0 | ||
while (index < str.length) { | ||
var eqIdx = str.indexOf('=', index) | ||
var dec = (options && options.decode) || decode; | ||
var index = 0; | ||
var eqIdx = 0; | ||
var endIdx = 0; | ||
do { | ||
eqIdx = str.indexOf('=', index); | ||
// no more cookie pairs | ||
if (eqIdx === -1) { | ||
break | ||
break; | ||
} | ||
var endIdx = str.indexOf(';', index) | ||
endIdx = str.indexOf(';', index); | ||
if (endIdx === -1) { | ||
endIdx = str.length | ||
} else if (endIdx < eqIdx) { | ||
endIdx = len; | ||
} else if (eqIdx > endIdx) { | ||
// backtrack on prior semicolon | ||
index = str.lastIndexOf(';', eqIdx - 1) + 1 | ||
continue | ||
index = str.lastIndexOf(';', eqIdx - 1) + 1; | ||
continue; | ||
} | ||
var key = str.slice(index, eqIdx).trim() | ||
var keyStartIdx = startIndex(str, index, eqIdx); | ||
var keyEndIdx = endIndex(str, eqIdx, keyStartIdx); | ||
var key = str.slice(keyStartIdx, keyEndIdx); | ||
// only assign once | ||
if (undefined === obj[key]) { | ||
var val = str.slice(eqIdx + 1, endIdx).trim() | ||
var valStartIdx = startIndex(str, eqIdx + 1, endIdx); | ||
var valEndIdx = endIndex(str, endIdx, valStartIdx); | ||
// quoted values | ||
if (val.charCodeAt(0) === 0x22) { | ||
val = val.slice(1, -1) | ||
if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) { | ||
valStartIdx++; | ||
valEndIdx--; | ||
} | ||
var val = str.slice(valStartIdx, valEndIdx); | ||
obj[key] = tryDecode(val, dec); | ||
@@ -92,3 +148,3 @@ } | ||
index = endIdx + 1 | ||
} | ||
} while (index < max); | ||
@@ -98,7 +154,23 @@ return obj; | ||
function startIndex(str, index, max) { | ||
do { | ||
var code = str.charCodeAt(index); | ||
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index; | ||
} while (++index < max); | ||
return max; | ||
} | ||
function endIndex(str, index, min) { | ||
while (index > min) { | ||
var code = str.charCodeAt(--index); | ||
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index + 1; | ||
} | ||
return min; | ||
} | ||
/** | ||
* Serialize data into a cookie header. | ||
* | ||
* Serialize the a name value pair into a cookie string suitable for | ||
* http headers. An optional options object specified cookie parameters. | ||
* Serialize a name value pair into a cookie string suitable for | ||
* http headers. An optional options object specifies cookie parameters. | ||
* | ||
@@ -123,3 +195,3 @@ * serialize('foo', 'bar', { httpOnly: true }) | ||
if (!fieldContentRegExp.test(name)) { | ||
if (!cookieNameRegExp.test(name)) { | ||
throw new TypeError('argument name is invalid'); | ||
@@ -130,3 +202,3 @@ } | ||
if (value && !fieldContentRegExp.test(value)) { | ||
if (value && !cookieValueRegExp.test(value)) { | ||
throw new TypeError('argument val is invalid'); | ||
@@ -140,3 +212,3 @@ } | ||
if (isNaN(maxAge) || !isFinite(maxAge)) { | ||
if (!isFinite(maxAge)) { | ||
throw new TypeError('option maxAge is invalid') | ||
@@ -149,3 +221,3 @@ } | ||
if (opt.domain) { | ||
if (!fieldContentRegExp.test(opt.domain)) { | ||
if (!domainValueRegExp.test(opt.domain)) { | ||
throw new TypeError('option domain is invalid'); | ||
@@ -158,3 +230,3 @@ } | ||
if (opt.path) { | ||
if (!fieldContentRegExp.test(opt.path)) { | ||
if (!pathValueRegExp.test(opt.path)) { | ||
throw new TypeError('option path is invalid'); | ||
@@ -161,0 +233,0 @@ } |
{ | ||
"name": "cookie", | ||
"description": "HTTP server cookie parsing and serialization", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"author": "Roman Shtylman <shtylman@gmail.com>", | ||
@@ -32,2 +32,3 @@ "contributors": [ | ||
], | ||
"main": "index.js", | ||
"engines": { | ||
@@ -42,5 +43,4 @@ "node": ">= 0.6" | ||
"test-cov": "nyc --reporter=html --reporter=text npm test", | ||
"update-bench": "node scripts/update-benchmark.js", | ||
"version": "node scripts/version-history.js && git add HISTORY.md" | ||
"update-bench": "node scripts/update-benchmark.js" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unstable ownership
Supply chain riskA new collaborator has begun publishing package versions. Package stability and security risk may be elevated.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
284
23253
5
1
1