125 lines
3.6 KiB
JavaScript
125 lines
3.6 KiB
JavaScript
/** RFC 6265-ish cookie jar (first-party default). */
|
|
|
|
function bareSummonCookieHostMatch(domain, host) {
|
|
var d = String(domain || '')
|
|
.replace(/^\./, '')
|
|
.toLowerCase()
|
|
var h = String(host || '').toLowerCase()
|
|
if (!d || !h) return false
|
|
if (h === d) return true
|
|
return h.length > d.length && h.slice(h.length - d.length - 1) === '.' + d
|
|
}
|
|
|
|
function bareSummonCookiePathMatch(path, reqPath) {
|
|
var p = path || '/'
|
|
var r = reqPath || '/'
|
|
if (r === p) return true
|
|
if (r.indexOf(p) === 0) {
|
|
if (p.charAt(p.length - 1) === '/') return true
|
|
return r.charAt(p.length) === '/'
|
|
}
|
|
return false
|
|
}
|
|
|
|
function bareSummonParseSetCookie(raw, pageUrl) {
|
|
var s = String(raw || '')
|
|
var parts = s.split(';')
|
|
var nv = parts[0] || ''
|
|
var eq = nv.indexOf('=')
|
|
if (eq < 0) return null
|
|
var name = nv.slice(0, eq).trim()
|
|
var value = nv.slice(eq + 1).trim()
|
|
if (!name) return null
|
|
var rec = {
|
|
name: name,
|
|
value: value,
|
|
domain: '',
|
|
path: '/',
|
|
secure: false,
|
|
httpOnly: false,
|
|
expires: 0
|
|
}
|
|
for (var i = 1; i < parts.length; i++) {
|
|
var bit = parts[i].trim()
|
|
var e2 = bit.indexOf('=')
|
|
var k = (e2 < 0 ? bit : bit.slice(0, e2)).trim().toLowerCase()
|
|
var v = e2 < 0 ? '' : bit.slice(e2 + 1).trim()
|
|
if (k === 'domain') rec.domain = v.replace(/^\./, '').toLowerCase()
|
|
else if (k === 'path') rec.path = v || '/'
|
|
else if (k === 'secure') rec.secure = true
|
|
else if (k === 'httponly') rec.httpOnly = true
|
|
else if (k === 'max-age') {
|
|
var n = parseInt(v, 10)
|
|
if (Number.isFinite(n)) rec.expires = Date.now() + n * 1000
|
|
}
|
|
}
|
|
var u = bareSummonParseUrl(pageUrl)
|
|
if (!rec.domain && u) rec.domain = u.hostname
|
|
if ((!rec.path || rec.path === '/') && u && u.pathname) {
|
|
var slash = u.pathname.lastIndexOf('/')
|
|
rec.path = slash > 0 ? u.pathname.slice(0, slash) : '/'
|
|
}
|
|
if (u && rec.secure && u.protocol !== 'https:') return null
|
|
return rec
|
|
}
|
|
|
|
function bareSummonCreateCookieJar() {
|
|
var list = []
|
|
return {
|
|
list: list,
|
|
put: function (setCookieLine, pageUrl, opts) {
|
|
var rec = bareSummonParseSetCookie(setCookieLine, pageUrl)
|
|
if (!rec) return false
|
|
var u = bareSummonParseUrl(pageUrl)
|
|
if (
|
|
u &&
|
|
rec.domain &&
|
|
!bareSummonCookieHostMatch(rec.domain, u.hostname)
|
|
) {
|
|
return false
|
|
}
|
|
var third = opts && opts.thirdParty
|
|
if (!third && u && rec.domain && rec.domain !== u.hostname) {
|
|
/* first-party only: allow subdomain of page host */
|
|
if (!bareSummonCookieHostMatch(rec.domain, u.hostname)) return false
|
|
}
|
|
for (var i = list.length - 1; i >= 0; i--) {
|
|
if (
|
|
list[i].name === rec.name &&
|
|
list[i].domain === rec.domain &&
|
|
list[i].path === rec.path
|
|
) {
|
|
list.splice(i, 1)
|
|
}
|
|
}
|
|
list.push(rec)
|
|
return true
|
|
},
|
|
headerFor: function (pageUrl) {
|
|
var u = bareSummonParseUrl(pageUrl)
|
|
if (!u) return ''
|
|
var now = Date.now()
|
|
var bits = []
|
|
for (var i = 0; i < list.length; i++) {
|
|
var c = list[i]
|
|
if (c.expires && c.expires < now) continue
|
|
if (!bareSummonCookieHostMatch(c.domain, u.hostname)) continue
|
|
if (!bareSummonCookiePathMatch(c.path, u.pathname)) continue
|
|
if (c.secure && u.protocol !== 'https:') continue
|
|
bits.push(c.name + '=' + c.value)
|
|
}
|
|
return bits.join('; ')
|
|
},
|
|
toJSON: function () {
|
|
return list.slice()
|
|
},
|
|
load: function (arr) {
|
|
list.length = 0
|
|
if (!Array.isArray(arr)) return
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (arr[i] && arr[i].name) list.push(arr[i])
|
|
}
|
|
}
|
|
}
|
|
}
|