about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer/container.nim7
-rw-r--r--src/config/config.nim19
-rw-r--r--src/config/toml.nim57
-rw-r--r--src/display/pager.nim15
4 files changed, 81 insertions, 17 deletions
diff --git a/src/buffer/container.nim b/src/buffer/container.nim
index a148e0e1..a08f4cb0 100644
--- a/src/buffer/container.nim
+++ b/src/buffer/container.nim
@@ -97,8 +97,11 @@ type
     events*: Deque[ContainerEvent]
     startpos: Option[CursorPosition]
     hasstart: bool
+    redirectdepth*: int
 
-proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource, cookiejar: CookieJar, title = ""): Container =
+proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource,
+                cookiejar: CookieJar, title = "",
+                redirectdepth = 0): Container =
   let attrs = getWindowAttributes(stdout)
   let config = config.getBufferConfig(source.location, cookiejar)
   let ostream = dispatcher.forkserver.ostream
@@ -112,7 +115,7 @@ proc newBuffer*(dispatcher: Dispatcher, config: Config, source: BufferSource, co
   result = Container(
     source: source, attrs: attrs, width: attrs.width,
     height: attrs.height - 1, contenttype: source.contenttype,
-    title: title, config: config
+    title: title, config: config, redirectdepth: redirectdepth
   )
   istream.sread(result.process)
   result.pos.setx = -1
diff --git a/src/config/config.nim b/src/config/config.nim
index 73072763..16e1c652 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -315,14 +315,17 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
         assert conf.url.isSome != conf.host.isSome
         config.siteconf.add(conf)
     of "omnirule":
-      for v in v:
-        var rule = StaticOmniRule()
-        for k, v in v:
-          case k
-          of "match": rule.match = v.s
-          of "substitute-url": rule.subst = v.s
-        if rule.match != "":
-          config.omnirules.add(rule)
+      if v.vt == VALUE_ARRAY and v.a.len == 0:
+        config.omnirules.setLen(0)
+      else:
+        for v in v:
+          var rule = StaticOmniRule()
+          for k, v in v:
+            case k
+            of "match": rule.match = v.s
+            of "substitute": rule.subst = v.s
+          if rule.match != "":
+            config.omnirules.add(rule)
 
 proc parseConfig(config: Config, dir: string, stream: Stream) =
   config.parseConfig(dir, parseToml(stream))
diff --git a/src/config/toml.nim b/src/config/toml.nim
index 2c4550b5..89277d24 100644
--- a/src/config/toml.nim
+++ b/src/config/toml.nim
@@ -323,7 +323,10 @@ proc consumeNoState(state: var TomlParser): bool =
             node.map[table.key[i]] = TomlValue(vt: VALUE_TABLE, t: t2)
             node = t2
         if table.key[^1] in node.map:
-          let last = node.map[table.key[^1]]
+          var last = node.map[table.key[^1]]
+          if last.vt == VALUE_ARRAY and last.a.len == 0:
+            last = TomlValue(vt: VALUE_TABLE_ARRAY)
+            node.map[table.key[^1]] = last
           if last.vt != VALUE_TABLE_ARRAY:
             let key = table.key.join('.')
             state.valueError(fmt"re-definition of node {key} as table array (was {last.vt})")
@@ -396,11 +399,59 @@ proc consumeArray(state: var TomlParser): TomlValue =
     of ',':
       if val == nil:
         state.syntaxError("comma without element")
-      result.a.add(val)
+      if val.vt == VALUE_TABLE:
+        # inline table array
+        result = TomlValue(vt: VALUE_TABLE_ARRAY)
+        result.ta.add(val.t)
+      else:
+        result.a.add(val)
     else:
+      if val != nil:
+        state.syntaxError("missing comma")
       state.reconsume()
       val = state.consumeValue()
 
+proc consumeInlineTable(state: var TomlParser): TomlValue =
+  result = TomlValue(vt: VALUE_TABLE, t: TomlTable())
+  var key: seq[string]
+  var haskey: bool
+  var val: TomlValue
+  while state.has():
+    let c = state.consume()
+    case c
+    of ' ', '\t', '\n': discard
+    of '}':
+      if val != nil:
+        result.a.add(val)
+      break
+    of ',':
+      if key.len == 0:
+        state.syntaxError("missing key")
+      if val == nil:
+        state.syntaxError("comma without element")
+      var table = result.t
+      for i in 0 ..< key.high:
+        let k = key[i]
+        if k in table.map:
+          state.syntaxError(fmt"invalid re-definition of key {k}")
+        else:
+          let node = TomlTable()
+          table.map[k] = TomlValue(vt: VALUE_TABLE, t: node)
+          table = node
+      let k = key[^1]
+      if k in table.map:
+        state.syntaxError(fmt"invalid re-definition of key {k}")
+      table.map[k] = val
+    else:
+      if val != nil:
+        state.syntaxError("missing comma")
+      if not haskey:
+        key = state.consumeKey()
+        haskey = true
+      else:
+        state.reconsume()
+        val = state.consumeValue()
+
 proc consumeValue(state: var TomlParser): TomlValue =
   while state.has():
     let c = state.consume()
@@ -417,6 +468,8 @@ proc consumeValue(state: var TomlParser): TomlValue =
       #TODO date-time
     of '[':
       return state.consumeArray()
+    of '{':
+      return state.consumeInlineTable()
     elif c.isBare():
       let s = state.consumeBare(c)
       case s
diff --git a/src/display/pager.nim b/src/display/pager.nim
index 06b28346..66280edc 100644
--- a/src/display/pager.nim
+++ b/src/display/pager.nim
@@ -483,7 +483,9 @@ proc applySiteconf(pager: Pager, request: Request) =
       pager.cookiejars[request.url.host] = newCookieJar(request.url)
 
 # Load request in a new buffer.
-proc gotoURL*(pager: Pager, request: Request, prevurl = none(URL), ctype = none(string), replace: Container = nil) =
+proc gotoURL*(pager: Pager, request: Request, prevurl = none(URL),
+              ctype = none(string), replace: Container = nil,
+              redirectdepth = 0) =
   pager.applySiteconf(request)
   if prevurl.isnone or not prevurl.get.equals(request.url, true) or
       request.url.hash == "" or request.httpmethod != HTTP_GET:
@@ -500,7 +502,7 @@ proc gotoURL*(pager: Pager, request: Request, prevurl = none(URL), ctype = none(
       location: request.url
     )
     let cookiejar = pager.cookiejars.getOrDefault(request.url.host)
-    let container = pager.dispatcher.newBuffer(pager.config, source, cookiejar)
+    let container = pager.dispatcher.newBuffer(pager.config, source, cookiejar, redirectdepth = redirectdepth)
     if replace != nil:
       container.replace = replace
       container.copyCursorPos(container.replace)
@@ -711,9 +713,12 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo
     if pager.container == container:
       pager.authorize()
   of REDIRECT:
-    let redirect = event.location
-    pager.alert("Redirecting to " & $redirect)
-    pager.gotoURL(newRequest(redirect), some(pager.container.source.location), replace = pager.container)
+    if container.redirectdepth < 10:
+      let redirect = event.location
+      pager.alert("Redirecting to " & $redirect)
+      pager.gotoURL(newRequest(redirect), some(container.source.location), replace = container, redirectdepth = container.redirectdepth + 1)
+    else:
+      pager.alert("Error: maximum redirection depth reached")
   of ANCHOR:
     var url2 = newURL(container.source.location)
     url2.hash(event.anchor)