about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-13 13:08:33 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-13 13:08:33 +0100
commit672ab553c4a2b10a703ea40e049eda52db149a93 (patch)
tree10c581ab40702e113bffe6605c58a640ac5095ee /src
parentf3e2cb7bfa4517155a2c6675e6310f17d8ca4d89 (diff)
downloadchawan-672ab553c4a2b10a703ea40e049eda52db149a93.tar.gz
Add more cookie options
Diffstat (limited to 'src')
-rw-r--r--src/buffer/container.nim7
-rw-r--r--src/config/config.nim18
-rw-r--r--src/display/client.nim4
-rw-r--r--src/display/pager.nim13
-rw-r--r--src/io/loader.nim7
-rw-r--r--src/io/urlfilter.nim30
-rw-r--r--src/js/regex.nim3
-rw-r--r--src/types/cookie.nim18
8 files changed, 69 insertions, 31 deletions
diff --git a/src/buffer/container.nim b/src/buffer/container.nim
index a08f4cb0..67c45aa2 100644
--- a/src/buffer/container.nim
+++ b/src/buffer/container.nim
@@ -34,8 +34,7 @@ type
 
   ContainerEventType* = enum
     NO_EVENT, FAIL, SUCCESS, NEEDS_AUTH, REDIRECT, ANCHOR, NO_ANCHOR, UPDATE,
-    READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT, LOADED,
-    SET_COOKIE
+    READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT, LOADED
 
   ContainerEvent* = object
     case t*: ContainerEventType
@@ -55,8 +54,6 @@ type
       msg*: string
     of UPDATE:
       force*: bool
-    of SET_COOKIE:
-      cookies*: seq[Cookie]
     else: discard
 
   Highlight* = ref object
@@ -649,7 +646,7 @@ proc load*(container: Container) =
       if res.code == 0:
         container.triggerEvent(SUCCESS)
         if res.cookies.len > 0 and container.config.cookiejar != nil: # accept cookies
-          container.triggerEvent(ContainerEvent(t: SET_COOKIE, cookies: res.cookies))
+          container.config.cookiejar.cookies.add(res.cookies)
         container.setLoadInfo("Connected to " & $container.source.location & ". Downloading...")
         if res.needsAuth:
           container.triggerEvent(NEEDS_AUTH)
diff --git a/src/config/config.nim b/src/config/config.nim
index e00724df..850ccb71 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -27,6 +27,8 @@ type
     host: Option[string]
     subst: Option[string]
     cookie: bool
+    thirdpartycookie: seq[string]
+    sharecookiejar: Option[string]
 
   StaticOmniRule = object
     match: string
@@ -37,6 +39,8 @@ type
     host*: Option[Regex]
     subst*: (proc(s: URL): Option[URL])
     cookie*: bool
+    thirdpartycookie*: seq[Regex]
+    sharecookiejar*: Option[string]
 
   OmniRule* = object
     match*: Regex
@@ -85,18 +89,21 @@ func getForkServerConfig*(config: Config): ForkServerConfig =
 
 func getBufferConfig*(config: Config, location: URL, cookiejar: CookieJar): BufferConfig =
   result.userstyle = config.stylesheet
-  result.filter = newURLFilter(scheme = some(location.scheme))
+  result.filter = newURLFilter(scheme = some(location.scheme), default = true)
   result.cookiejar = cookiejar
 
 proc getSiteConfig*(config: Config, jsctx: JSContext): seq[SiteConfig] =
   for sc in config.siteconf:
     var conf = SiteConfig(
       cookie: sc.cookie,
+      sharecookiejar: sc.sharecookiejar
     )
     if sc.url.isSome:
       conf.url = compileRegex(sc.url.get, 0)
     elif sc.host.isSome:
       conf.host = compileRegex(sc.host.get, 0)
+    for rule in sc.thirdpartycookie:
+      conf.thirdpartycookie.add(compileRegex(rule, 0).get)
     if sc.subst.isSome:
       let fun = jsctx.eval(sc.subst.get, "<siteconf>", JS_EVAL_TYPE_GLOBAL)
       let f = getJSFunction[URL, URL](jsctx, fun.val)
@@ -242,7 +249,7 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
     of "network":
       for k, v in v:
         case k
-        of "max-redirects":
+        of "max-redirect":
           config.maxredirect = int(v.i)
         of "prepend-https":
           config.prependhttps = v.b
@@ -321,6 +328,13 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
           of "host": conf.host = some(v.s)
           of "rewrite-url": conf.subst = some(v.s)
           of "cookie": conf.cookie = v.b
+          of "third-party-cookie":
+            if v.vt == VALUE_STRING:
+              conf.thirdpartycookie = @[v.s]
+            else:
+              for v in v.a:
+                conf.thirdpartycookie.add(v.s)
+          of "share-cookie-jar": conf.sharecookiejar = some(v.s)
         assert conf.url.isSome != conf.host.isSome
         config.siteconf.add(conf)
     of "omnirule":
diff --git a/src/display/client.nim b/src/display/client.nim
index 90945968..9ca2ac68 100644
--- a/src/display/client.nim
+++ b/src/display/client.nim
@@ -403,11 +403,11 @@ proc launchClient*(client: Client, pages: seq[string], ctype: Option[string], du
   var tty: File
   var dump = dump
   if not dump:
-    if stdin.isatty():
+    if not stdin.isatty():
       tty = stdin
     elif stdout.isatty():
       discard open(tty, "/dev/tty", fmRead)
-    else:
+    if tty == nil:
       dump = true
   client.ssock = initServerSocket(false)
   client.selector = newSelector[Container]()
diff --git a/src/display/pager.nim b/src/display/pager.nim
index d1eca1d7..3825f088 100644
--- a/src/display/pager.nim
+++ b/src/display/pager.nim
@@ -470,7 +470,7 @@ proc windowChange*(pager: Pager, attrs: WindowAttributes) =
 
 proc applySiteconf(pager: Pager, request: Request) =
   let url = $request.url
-  let host = $request.url.host
+  let host = request.url.host
   for sc in pager.siteconf:
     if sc.url.isSome and not sc.url.get.exec(url).success:
       continue
@@ -480,8 +480,11 @@ proc applySiteconf(pager: Pager, request: Request) =
       let s = sc.subst(request.url)
       if s.isSome and s.get != nil:
         request.url = s.get
-    if sc.cookie and request.url.host notin pager.cookiejars:
-      pager.cookiejars[request.url.host] = newCookieJar(request.url)
+    if sc.cookie:
+      # host/url might have changed by now
+      let jarid = sc.sharecookiejar.get(request.url.host)
+      if jarid notin pager.cookiejars:
+        pager.cookiejars[jarid] = newCookieJar(request.url, sc.thirdpartycookie)
 
 # Load request in a new buffer.
 proc gotoURL*(pager: Pager, request: Request, prevurl = none(URL),
@@ -749,10 +752,6 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo
     if pager.container == container:
       pager.alert(event.msg)
       pager.refreshStatusMsg()
-  of SET_COOKIE:
-    let host = container.source.location.host
-    if host in pager.cookiejars:
-      pager.cookiejars[host].cookies.add(event.cookies)
   of NO_EVENT: discard
   return true
 
diff --git a/src/io/loader.nim b/src/io/loader.nim
index 671b9ca3..0b0f5531 100644
--- a/src/io/loader.nim
+++ b/src/io/loader.nim
@@ -118,9 +118,10 @@ proc runFileLoader*(fd: cint, defaultHeaders: HeaderList, filter: URLFilter, coo
             if k notin request.headers.table:
               request.headers.table[k] = v
           if cookiejar != nil and cookiejar.cookies.len > 0:
-            if request.url.host == cookiejar.location.host:
-              if "Cookie" notin request.headers.table:
-                request.headers["Cookie"] = $cookiejar
+            if "Cookie" notin request.headers.table:
+              let cookie = cookiejar.serialize(request.url)
+              if cookie != "":
+                request.headers["Cookie"] = cookie
           loadResource(request, stream)
         stream.close()
       of QUIT:
diff --git a/src/io/urlfilter.nim b/src/io/urlfilter.nim
index 6c0b71c9..29dad8c6 100644
--- a/src/io/urlfilter.nim
+++ b/src/io/urlfilter.nim
@@ -1,20 +1,36 @@
 import options
 
+import js/regex
 import types/url
 
+#TODO add denyhost/s for blocklists
 type URLFilter* = object
   scheme: Option[string]
-  host: Option[string]
+  allowhost: Option[string]
+  allowhosts: Option[seq[Regex]]
+  default: bool
 
-proc newURLFilter*(scheme = none(string), host = none(string)): URLFilter =
+proc newURLFilter*(scheme = none(string), allowhost = none(string),
+                   allowhosts = none(seq[Regex]), default = false): URLFilter =
   return URLFilter(
     scheme: scheme,
-    host: host
+    allowhost: allowhost,
+    allowhosts: allowhosts,
+    default: default
   )
 
-func match*(filter: URLFilter, url: URL): bool =
+# Filters as follows:
+# If scheme is given, only URLs with the same scheme are matched.
+# Then, allowhost and allowhosts are checked; if none of these match the host,
+# the function returns the value of `default'.
+proc match*(filter: URLFilter, url: URL): bool =
   if filter.scheme.isSome and filter.scheme.get != url.scheme:
     return false
-  if filter.host.isSome and filter.host.get != url.host:
-    return false
-  return true
+  let host = url.host
+  if filter.allowhost.isSome and filter.allowhost.get == host:
+    return true
+  if filter.allowhosts.isSome:
+    for regex in filter.allowhosts.get:
+      if regex.match(host):
+        return true
+  return filter.default
diff --git a/src/js/regex.nim b/src/js/regex.nim
index d65e5a29..a4652373 100644
--- a/src/js/regex.nim
+++ b/src/js/regex.nim
@@ -215,3 +215,6 @@ proc exec*(regex: Regex, str: string, start = 0, length = str.len): RegexResult
           e8 += r.size()
         result.captures.add((s8, e8))
   dealloc(capture)
+
+proc match*(regex: Regex, str: string, start = 0, length = str.len): bool =
+  return regex.exec(str, start, length).success
diff --git a/src/types/cookie.nim b/src/types/cookie.nim
index db5a4de3..c848813d 100644
--- a/src/types/cookie.nim
+++ b/src/types/cookie.nim
@@ -2,7 +2,9 @@ import options
 import strutils
 import times
 
+import io/urlfilter
 import js/javascript
+import js/regex
 import types/url
 import utils/twtstr
 
@@ -19,7 +21,7 @@ type
     path {.jsget.}: string
 
   CookieJar* = ref object
-    location*: URL
+    filter: URLFilter
     cookies*: seq[Cookie]
 
 proc parseCookieDate(val: string): Option[DateTime] =
@@ -107,13 +109,15 @@ proc parseCookieDate(val: string): Option[DateTime] =
   var dateTime = dateTime(year, Month(month), MonthdayRange(dayOfMonth), HourRange(time[0]), MinuteRange(time[1]), SecondRange(time[2]))
   return some(dateTime)
 
-proc `$`*(cookiejar: CookieJar): string =
+proc serialize*(cookiejar: CookieJar, location: URL): string =
+  if not cookiejar.filter.match(location):
+    return "" # fail
   let t = now().toTime().toUnix()
   for i in countdown(cookiejar.cookies.high, 0):
     let cookie = cookiejar.cookies[i]
     if cookie.expires <= t:
       cookiejar.cookies.delete(i)
-    elif cookie.domain == "" or cookiejar.location.host.endsWith(cookie.domain):
+    elif cookie.domain == "" or location.host.endsWith(cookie.domain):
       result.percentEncode(cookie.name, UserInfoPercentEncodeSet)
       result &= "="
       result.percentEncode(cookie.value, UserInfoPercentEncodeSet)
@@ -152,9 +156,13 @@ proc newCookie*(str: string): Cookie {.jsctor.} =
     of "domain": cookie.domain = val
   return cookie
 
-proc newCookieJar*(location: URL): CookieJar =
+proc newCookieJar*(location: URL, allowhosts: seq[Regex]): CookieJar =
   return CookieJar(
-    location: location
+    filter: newURLFilter(
+      scheme = some(location.scheme),
+      allowhost = some(location.host),
+      allowhosts = some(allowhosts)
+    )
   )
 
 proc addCookieModule*(ctx: JSContext) =