diff options
author | bptato <nincsnevem662@gmail.com> | 2025-05-02 17:17:40 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-05-02 17:45:19 +0200 |
commit | e512ff078d6afda9a8712dfad793182dd19df53a (patch) | |
tree | 8220e6e7fece8d3abf763cf1cf2c1adfd3640671 | |
parent | a3ef823e8224b908a14690aa3fb2a460246e2ca8 (diff) | |
download | chawan-e512ff078d6afda9a8712dfad793182dd19df53a.tar.gz |
container: support Refresh header
-rw-r--r-- | src/local/container.nim | 27 | ||||
-rw-r--r-- | src/server/buffer.nim | 40 | ||||
-rw-r--r-- | src/server/headers.nim | 43 |
3 files changed, 63 insertions, 47 deletions
diff --git a/src/local/container.nim b/src/local/container.nim index c4f20523..1b621d87 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -188,6 +188,7 @@ type cachedImages*: seq[CachedImage] luctx: LUContext redraw*: bool + refreshHeader: string jsDestructor(Highlight) jsDestructor(Container) @@ -1521,14 +1522,23 @@ proc onload(container: Container; res: int) = container.onReadLine(res.focus) ) if container.config.metaRefresh != mrNever: - container.iface.checkRefresh().then(proc(res: CheckRefreshResult) = - if res.n >= 0: - container.triggerEvent(ContainerEvent( - t: cetMetaRefresh, - refreshIn: res.n, - refreshURL: if res.url != nil: res.url else: container.url - )) - ) + let res = parseRefresh(container.refreshHeader, container.url) + container.refreshHeader = "" + if res.n != -1: + container.triggerEvent(ContainerEvent( + t: cetMetaRefresh, + refreshIn: res.n, + refreshURL: if res.url != nil: res.url else: container.url + )) + else: + container.iface.checkRefresh().then(proc(res: CheckRefreshResult) = + if res.n >= 0: + container.triggerEvent(ContainerEvent( + t: cetMetaRefresh, + refreshIn: res.n, + refreshURL: if res.url != nil: res.url else: container.url + )) + ) else: container.setLoadInfo(convertSize(res) & " loaded") discard container.iface.load().then(proc(res: int) = @@ -1575,6 +1585,7 @@ proc applyResponse*(container: Container; response: Response; if container.charsetStack.len == 0: container.charsetStack.add(DefaultCharset) container.charset = container.charsetStack[^1] + container.refreshHeader = response.headers.getOrDefault("Refresh") proc remoteCancel*(container: Container) = if container.iface != nil: diff --git a/src/server/buffer.nim b/src/server/buffer.nim index c36caecf..e898ee86 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -690,12 +690,6 @@ proc gotoAnchor*(buffer: Buffer; anchor: string; autofocus, target: bool): let y = max(offset.y div buffer.attrs.ppl, 0).toInt return GotoAnchorResult(found: true, x: x, y: y, focus: focus) -type CheckRefreshResult* = object - # n is timeout in millis. -1 => not found - n*: int - # url == nil => self - url*: URL - proc checkRefresh*(buffer: Buffer): CheckRefreshResult {.proxy.} = if buffer.navigateUrl != nil: let url = buffer.navigateUrl @@ -706,39 +700,7 @@ proc checkRefresh*(buffer: Buffer): CheckRefreshResult {.proxy.} = let element = buffer.document.findMetaRefresh() if element == nil: return CheckRefreshResult(n: -1) - let s = element.attr(satContent) - var i = s.skipBlanks(0) - let s0 = s.until(AllChars - AsciiDigit, i) - let x = parseUInt32(s0, allowSign = false) - if s0 != "": - if x.isNone and (i >= s.len or s[i] != '.'): - return CheckRefreshResult(n: -1) - var n = int(x.get(0) * 1000) - i = s.skipBlanks(i + s0.len) - if i < s.len and s[i] == '.': - inc i - let s1 = s.until(AllChars - AsciiDigit, i) - if s1 != "": - n += int(parseUInt32(s1, allowSign = false).get(0)) - i = s.skipBlanks(i + s1.len) - if i >= s.len: # just reload this page - return CheckRefreshResult(n: n) - if s[i] notin {',', ';'}: - return CheckRefreshResult(n: -1) - i = s.skipBlanks(i + 1) - if s.toOpenArray(i, s.high).startsWithIgnoreCase("url="): - i = s.skipBlanks(i + "url=".len) - var q = false - if i < s.len and s[i] in {'"', '\''}: - q = true - inc i - var s2 = s.substr(i) - if q and s2.len > 0 and s[^1] in {'"', '\''}: - s2.setLen(s2.high) - let url = buffer.document.parseURL(s2) - if url.isNone: - return CheckRefreshResult(n: -1) - return CheckRefreshResult(n: n, url: url.get) + return parseRefresh(element.attr(satContent), buffer.url) proc hasTask(buffer: Buffer; cmd: BufferCommand): bool = return buffer.tasks[cmd] != 0 diff --git a/src/server/headers.nim b/src/server/headers.nim index 48959e07..c6fa0566 100644 --- a/src/server/headers.nim +++ b/src/server/headers.nim @@ -7,6 +7,7 @@ import monoucha/jserror import monoucha/quickjs import monoucha/tojs import types/opt +import types/url import utils/twtstr type @@ -302,5 +303,47 @@ func getAllNoComma*(headers: Headers; k: string): seq[string] = return p[] return @[] +type CheckRefreshResult* = object + # n is timeout in millis. -1 => not found + n*: int + # url == nil => self + url*: URL + +func parseRefresh*(s: string; baseURL: URL): CheckRefreshResult = + var i = s.skipBlanks(0) + let s0 = s.until(AllChars - AsciiDigit, i) + let x = parseUInt32(s0, allowSign = false) + if s0 != "": + if x.isNone and (i >= s.len or s[i] != '.'): + return CheckRefreshResult(n: -1) + var n = int(x.get(0) * 1000) + i = s.skipBlanks(i + s0.len) + if i < s.len and s[i] == '.': + inc i + let s1 = s.until(AllChars - AsciiDigit, i) + if s1 != "": + n += int(parseUInt32(s1, allowSign = false).get(0)) + i = s.skipBlanks(i + s1.len) + elif s0 == "": # empty string or blanks + return CheckRefreshResult(n: -1) + if i >= s.len: # just reload this page + return CheckRefreshResult(n: n) + if s[i] notin {',', ';'}: + return CheckRefreshResult(n: -1) + i = s.skipBlanks(i + 1) + if s.toOpenArray(i, s.high).startsWithIgnoreCase("url="): + i = s.skipBlanks(i + "url=".len) + var q = false + if i < s.len and s[i] in {'"', '\''}: + q = true + inc i + var s2 = s.substr(i) + if q and s2.len > 0 and s[^1] in {'"', '\''}: + s2.setLen(s2.high) + let url = parseURL(s2, some(baseURL)) + if url.isNone: + return CheckRefreshResult(n: -1) + return CheckRefreshResult(n: n, url: url.get) + proc addHeadersModule*(ctx: JSContext) = ctx.registerType(Headers) |