diff options
author | bptato <nincsnevem662@gmail.com> | 2022-10-19 11:24:45 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-10-19 11:25:56 +0200 |
commit | 08a758ed7a06e1bff8994c01d6c5d317d400ccf9 (patch) | |
tree | cb53cf39ebd323491715eb569cc509c00edcae91 /src/types | |
parent | c4e2de9cd8cad7e28b33e68b1b76f9044fe510be (diff) | |
download | chawan-08a758ed7a06e1bff8994c01d6c5d317d400ccf9.tar.gz |
Implement tree buffers, fix a js bug, refactor
Diffstat (limited to 'src/types')
-rw-r--r-- | src/types/cookie.nim | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/types/cookie.nim b/src/types/cookie.nim new file mode 100644 index 00000000..b0578e44 --- /dev/null +++ b/src/types/cookie.nim @@ -0,0 +1,137 @@ +import options +import strutils +import times + +import js/javascript +import utils/twtstr + +type Cookie = ref object of RootObj + name {.jsget.}: string + value {.jsget.}: string + expires {.jsget.}: int64 # unix time + maxAge {.jsget.}: int64 + secure {.jsget.}: bool + httponly {.jsget.}: bool + samesite {.jsget.}: bool + domain {.jsget.}: string + path {.jsget.}: string + +proc parseCookieDate(val: string): Option[DateTime] = + # cookie-date + const Delimiters = {'\t', ' '..'/', ';'..'@', '['..'`', '{'..'~'} + const NonDigit = AllChars - AsciiDigit + var foundTime = false + var foundDayOfMonth = false + var foundMonth = false + var foundYear = false + # date-token-list + var time: array[3, int] + var dayOfMonth: int + var month: int + var year: int + for dateToken in val.split(Delimiters): + if dateToken == "": continue # *delimiter + if not foundTime: + block timeBlock: # test for time + let hmsTime = dateToken.until(NonDigit - {':'}) + var i = 0 + for timeField in hmsTime.split(':'): + if i > 2: break timeBlock # too many time fields + # 1*2DIGIT + if timeField.len != 1 and timeField.len != 2: break timeBlock + var timeFields: array[3, int] + for c in timeField: + if c notin AsciiDigit: break timeBlock + timeFields[i] *= 10 + timeFields[i] += c.decValue + time = timeFields + inc i + if i != 3: break timeBlock + foundTime = true + continue + if not foundDayOfMonth: + block dayOfMonthBlock: # test for day-of-month + let digits = dateToken.until(NonDigit) + if digits.len != 1 and digits.len != 2: break dayOfMonthBlock + var n = 0 + for c in digits: + if c notin AsciiDigit: break dayOfMonthBlock + n *= 10 + n += c.decValue + dayOfMonth = n + foundDayOfMonth = true + continue + if not foundMonth: + block monthBlock: # test for month + if dateToken.len < 3: break monthBlock + case dateToken.substr(0, 2).toLower() + of "jan": month = 1 + of "feb": month = 2 + of "mar": month = 3 + of "apr": month = 4 + of "may": month = 5 + of "jun": month = 6 + of "jul": month = 7 + of "aug": month = 8 + of "sep": month = 9 + of "oct": month = 10 + of "nov": month = 11 + of "dec": month = 12 + else: break monthBlock + foundMonth = true + continue + if not foundYear: + block yearBlock: # test for year + let digits = dateToken.until(NonDigit) + if digits.len != 2 and digits.len != 4: break yearBlock + var n = 0 + for c in digits: + if c notin AsciiDigit: break yearBlock + n *= 10 + n += c.decValue + year = n + foundYear = true + continue + if not (foundDayOfMonth and foundMonth and foundYear and foundTime): return none(DateTime) + if dayOfMonth notin 0..31: return none(DateTime) + if year < 1601: return none(DateTime) + if time[0] > 23: return none(DateTime) + if time[1] > 59: return none(DateTime) + if time[2] > 59: return none(DateTime) + var dateTime = dateTime(year, Month(month), MonthdayRange(dayOfMonth), HourRange(time[0]), MinuteRange(time[1]), SecondRange(time[2])) + return some(dateTime) + +proc newCookie(str: string): Cookie {.jsctor.} = + let cookie = new(Cookie) + var first = true + for part in str.split(';'): + if first: + cookie.name = part.until('=') + cookie.value = part.after('=') + first = false + continue + let part = percentDecode(part).strip(leading = true, trailing = false, AsciiWhitespace) + var n = 0 + for i in 0..part.high: + if part[i] == '=': + n = i + break + if n == 0: + continue + let key = part.substr(0, n - 1) + let val = part.substr(n + 1) + case key.toLower() + of "expires": + let date = parseCookieDate(val) + if date.issome: + cookie.expires = date.get.toTime().toUnix() + of "max-age": cookie.maxAge = parseInt64(val) + of "secure": cookie.secure = true + of "httponly": cookie.httponly = true + of "samesite": cookie.samesite = true + of "path": cookie.path = val + of "domain": cookie.domain = val + return cookie + +proc addCookieModule*(ctx: JSContext) = + ctx.registerType(Cookie) |