diff options
-rw-r--r-- | doc/config.md | 2 | ||||
-rw-r--r-- | src/buffer/buffer.nim | 25 | ||||
-rw-r--r-- | src/buffer/container.nim | 7 | ||||
-rw-r--r-- | src/css/cssparser.nim | 7 | ||||
-rw-r--r-- | src/display/client.nim | 2 | ||||
-rw-r--r-- | src/io/http.nim | 5 | ||||
-rw-r--r-- | src/io/loader.nim | 3 | ||||
-rw-r--r-- | src/io/posixstream.nim | 33 | ||||
-rw-r--r-- | src/io/urlfilter.nim | 2 | ||||
-rw-r--r-- | src/ips/forkserver.nim | 7 | ||||
-rw-r--r-- | src/ips/serialize.nim | 6 | ||||
-rw-r--r-- | src/ips/socketstream.nim | 24 | ||||
-rw-r--r-- | src/js/regex.nim | 3 | ||||
-rw-r--r-- | src/types/cookie.nim | 10 |
14 files changed, 93 insertions, 43 deletions
diff --git a/doc/config.md b/doc/config.md index 4879621d..a044f719 100644 --- a/doc/config.md +++ b/doc/config.md @@ -259,7 +259,7 @@ Examples: ``` # Enable cookies on the orange website for log-in. [[siteconf]] -url = "^https://news.ycombinator.com/.*" +url = '^https://news\.ycombinator\.com/.*' cookie = true # Redirect npr.org to text.npr.org. diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim index b692e253..11492834 100644 --- a/src/buffer/buffer.nim +++ b/src/buffer/buffer.nim @@ -47,7 +47,8 @@ type BufferCommand* = enum LOAD, RENDER, WINDOW_CHANGE, FIND_ANCHOR, READ_SUCCESS, READ_CANCELED, CLICK, FIND_NEXT_LINK, FIND_PREV_LINK, FIND_NEXT_MATCH, FIND_PREV_MATCH, - GET_SOURCE, GET_LINES, UPDATE_HOVER, PASS_FD, CONNECT, GOTO_ANCHOR, CANCEL + GET_SOURCE, GET_LINES, UPDATE_HOVER, PASS_FD, CONNECT, GOTO_ANCHOR, CANCEL, + GET_TITLE BufferMatch* = object success*: bool @@ -233,7 +234,7 @@ macro proxy(fun: typed) = proxy0(`fun`) proxy1(`fun`) -func getTitle(node: StyledNode): string = +func getTitleAttr(node: StyledNode): string = if node == nil: return "" if node.t == STYLED_ELEMENT and node.node != nil: @@ -476,7 +477,7 @@ proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult {.pr result.repaint = true var upd = false - let title = thisnode.getTitle() + let title = thisnode.getTitleAttr() if title != "": upd = true buffer.hovertext = title @@ -606,8 +607,9 @@ proc load*(buffer: Buffer): tuple[atend: bool, lines, bytes: int] {.proxy.} = try: buffer.sstream.setPosition(op + buffer.available) let n = buffer.istream.readData(addr s[0], buffer.readbufsize) + assert n != 0 s.setLen(n) - result = (n == 0, buffer.lines.len, bytes) + result = (false, buffer.lines.len, n) buffer.sstream.setPosition(op) if buffer.readbufsize < BufferSize: buffer.readbufsize = min(BufferSize, buffer.readbufsize * 2) @@ -617,8 +619,9 @@ proc load*(buffer: Buffer): tuple[atend: bool, lines, bytes: int] {.proxy.} = bytes = buffer.available else: buffer.do_reshape() - if result.atend: - buffer.finishLoad() + except EOFError: + result = (true, buffer.lines.len, 0) + buffer.finishLoad() except ErrorAgain, ErrorWouldBlock: buffer.timeout = buffer.lasttimeout if buffer.readbufsize == 1: @@ -630,6 +633,10 @@ proc load*(buffer: Buffer): tuple[atend: bool, lines, bytes: int] {.proxy.} = buffer.readbufsize = buffer.readbufsize div 2 result = (false, buffer.lines.len, bytes) +proc getTitle*(buffer: Buffer): string {.proxy.} = + if buffer.document != nil: + return buffer.document.title + proc render*(buffer: Buffer): int {.proxy.} = buffer.do_reshape() return buffer.lines.len @@ -1081,9 +1088,9 @@ proc runBuffer(buffer: Buffer, rfd: int) = try: buffer.readCommand() except IOError: - #eprint "ERROR IN BUFFER", buffer.location - #eprint "MESSAGE:", getCurrentExceptionMsg() - #eprint getStackTrace(getCurrentException()) + #eprint "ERROR IN BUFFER", $buffer.location & "\nMESSAGE:", + # getCurrentExceptionMsg() & "\n", + # getStackTrace(getCurrentException()) break loop else: assert false diff --git a/src/buffer/container.nim b/src/buffer/container.nim index 67c45aa2..5c579c27 100644 --- a/src/buffer/container.nim +++ b/src/buffer/container.nim @@ -627,7 +627,12 @@ proc onload(container: Container, res: tuple[atend: bool, lines, bytes: int]) = discard container.iface.load().then(proc(res: tuple[atend: bool, lines, bytes: int]) = container.onload(res)) else: - container.iface.render().then(proc(lines: int): auto = + container.iface.getTitle().then(proc(title: string): auto = + if title != "": + container.title = title + container.triggerEvent(STATUS) + return container.iface.render() + ).then(proc(lines: int): auto = container.setNumLines(lines, true) container.needslines = true container.triggerEvent(LOADED) diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim index 6f26629b..b4a22e28 100644 --- a/src/css/cssparser.nim +++ b/src/css/cssparser.nim @@ -163,7 +163,10 @@ func peek(state: CSSTokenizerState, i: int = 0): char = proc has(state: var CSSTokenizerState, i: int = 0): bool = if state.at + i >= state.buf.len and not state.stream.atEnd(): - state.buf &= state.stream.readLine() & '\n' + try: + state.buf &= state.stream.readStr(256) + except EOFError: + return false return state.at + i < state.buf.len proc isValidEscape(a, b: char): bool = @@ -210,7 +213,7 @@ proc startsWithNumber(state: var CSSTokenizerState): bool = if state.has(2) and state.peek(2) in AsciiDigit: return true of '.': - if state.peek(1) in AsciiDigit: + if state.has(1) and state.peek(1) in AsciiDigit: return true elif state.peek() in AsciiDigit: return true diff --git a/src/display/client.nim b/src/display/client.nim index 9ca2ac68..34077055 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -403,7 +403,7 @@ proc launchClient*(client: Client, pages: seq[string], ctype: Option[string], du var tty: File var dump = dump if not dump: - if not stdin.isatty(): + if stdin.isatty(): tty = stdin elif stdout.isatty(): discard open(tty, "/dev/tty", fmRead) diff --git a/src/io/http.nim b/src/io/http.nim index bfd12a0b..36cd6473 100644 --- a/src/io/http.nim +++ b/src/io/http.nim @@ -54,12 +54,9 @@ proc curlWriteHeader(p: cstring, size: csize_t, nitems: csize_t, userdata: point return nitems proc curlWriteBody(p: cstring, size: csize_t, nmemb: csize_t, userdata: pointer): csize_t {.cdecl.} = - var s = newString(nmemb) - for i in 0..<nmemb: - s[i] = p[i] let stream = cast[Stream](userdata) if nmemb > 0: - stream.write(s) + stream.writeData(p, int(nmemb)) stream.flush() return nmemb diff --git a/src/io/loader.nim b/src/io/loader.nim index 0b0f5531..3e8baaf0 100644 --- a/src/io/loader.nim +++ b/src/io/loader.nim @@ -127,9 +127,8 @@ proc runFileLoader*(fd: cint, defaultHeaders: HeaderList, filter: URLFilter, coo of QUIT: stream.close() break - except IOError: + except EOFError: # End-of-file, quit. - # TODO this should be EOFError break stream.close() curl_global_cleanup() diff --git a/src/io/posixstream.nim b/src/io/posixstream.nim index 9a40ce9b..b686be9b 100644 --- a/src/io/posixstream.nim +++ b/src/io/posixstream.nim @@ -5,6 +5,7 @@ import streams type PosixStream* = ref object of Stream fd*: FileHandle + isend*: bool ErrorAgain* = object of IOError ErrorWouldBlock* = object of IOError @@ -14,17 +15,29 @@ type ErrorInvalid* = object of IOError proc psReadData(s: Stream, buffer: pointer, len: int): int = + assert len != 0 let s = cast[PosixStream](s) - result = read(s.fd, buffer, len) + while result < len: + let n = read(s.fd, buffer, len) + if n < 0: + if result == 0: + result = n + break + elif n == 0: + s.isend = true + break + result += n + if result == 0: + raise newException(EOFError, "eof") if result == -1: if errno == EAGAIN: - raise newException(ErrorAgain, "") + raise newException(ErrorAgain, "eagain") case errno - of EWOULDBLOCK: raise newException(ErrorWouldBlock, "") - of EBADF: raise newException(ErrorBadFD, "") - of EFAULT: raise newException(ErrorFault, "") - of EINVAL: raise newException(ErrorInvalid, "") - else: raise newException(IOError, $strerror(errno)) + of EWOULDBLOCK: raise newException(ErrorWouldBlock, "would block") + of EBADF: raise newException(ErrorBadFD, "bad fd") + of EFAULT: raise newException(ErrorFault, "fault") + of EINVAL: raise newException(ErrorInvalid, "invalid") + else: raise newException(IOError, $strerror(errno) & " (" & $errno & ")") proc psWriteData(s: Stream, buffer: pointer, len: int) = let s = cast[PosixStream](s) @@ -32,9 +45,13 @@ proc psWriteData(s: Stream, buffer: pointer, len: int) = if res == -1: raise newException(IOError, $strerror(errno)) +proc psAtEnd(s: Stream): bool = + return cast[PosixStream](s).isend + proc newPosixStream*(fd: FileHandle): PosixStream = return PosixStream( fd: fd, readDataImpl: psReadData, - writeDataImpl: psWriteData + writeDataImpl: psWriteData, + atEndImpl: psAtEnd ) diff --git a/src/io/urlfilter.nim b/src/io/urlfilter.nim index 29dad8c6..28bdef28 100644 --- a/src/io/urlfilter.nim +++ b/src/io/urlfilter.nim @@ -6,7 +6,7 @@ import types/url #TODO add denyhost/s for blocklists type URLFilter* = object scheme: Option[string] - allowhost: Option[string] + allowhost*: Option[string] allowhosts: Option[seq[Regex]] default: bool diff --git a/src/ips/forkserver.nim b/src/ips/forkserver.nim index e8904354..29463248 100644 --- a/src/ips/forkserver.nim +++ b/src/ips/forkserver.nim @@ -6,6 +6,7 @@ when defined(posix): import buffer/buffer import config/config import io/loader +import io/posixstream import io/request import io/urlfilter import io/window @@ -92,8 +93,8 @@ proc forkBuffer(ctx: var ForkServerContext): Pid = proc runForkServer() = var ctx: ForkServerContext - ctx.istream = newFileStream(stdin) - ctx.ostream = newFileStream(stdout) + ctx.istream = newPosixStream(stdin.getFileHandle()) + ctx.ostream = newPosixStream(stdout.getFileHandle()) while true: try: var cmd: ForkCommand @@ -124,7 +125,7 @@ proc runForkServer() = width_table = makewidthtable(config.ambiguous_double) SocketDirectory = config.tmpdir ctx.ostream.flush() - except IOError: + except EOFError: # EOF break ctx.istream.close() diff --git a/src/ips/serialize.nim b/src/ips/serialize.nim index ed35371a..05f05ac9 100644 --- a/src/ips/serialize.nim +++ b/src/ips/serialize.nim @@ -116,7 +116,11 @@ proc swrite*(stream: Stream, s: string) = proc sread*(stream: Stream, s: var string) = var len: int stream.sread(len) - stream.readStr(len, s) + if len > 0: + stream.readStr(len, s) + else: + s = "" + func slen*(s: string): int = slen(s.len) + s.len diff --git a/src/ips/socketstream.nim b/src/ips/socketstream.nim index 4f98517c..6d3e5cd9 100644 --- a/src/ips/socketstream.nim +++ b/src/ips/socketstream.nim @@ -15,26 +15,32 @@ type SocketStream* = ref object of Stream isend: bool proc sockReadData(s: Stream, buffer: pointer, len: int): int = + assert len != 0 let s = SocketStream(s) if s.blk: while result < len: let n = s.source.recv(cast[pointer](cast[int](buffer) + result), len - result) - result += n - if n == 0: - raise newException(EOFError, "") if n < 0: - result = n + if result == 0: + result = n + break + elif n == 0: + s.isend = true break + result += n else: result = s.source.recv(buffer, len) + if result == 0: + s.isend = true + raise newException(EOFError, "eof") if result < 0: if errno == EAGAIN: - raise newException(ErrorAgain, "") + raise newException(ErrorAgain, "eagain") case errno - of EWOULDBLOCK: raise newException(ErrorWouldBlock, "") - of EBADF: raise newException(ErrorBadFD, "") - of EFAULT: raise newException(ErrorFault, "") - of EINVAL: raise newException(ErrorInvalid, "") + of EWOULDBLOCK: raise newException(ErrorWouldBlock, "would block") + of EBADF: raise newException(ErrorBadFD, "bad fd") + of EFAULT: raise newException(ErrorFault, "fault") + of EINVAL: raise newException(ErrorInvalid, "invalid") else: raise newException(IOError, $strerror(errno)) elif result == 0: s.isend = true diff --git a/src/js/regex.nim b/src/js/regex.nim index a4652373..391cb46b 100644 --- a/src/js/regex.nim +++ b/src/js/regex.nim @@ -109,6 +109,9 @@ proc `=copy`(dest: var Regex, source: Regex) = dest.buf = source.buf dest.plen = source.plen +func `$`*(regex: Regex): string = + regex.buf + proc compileRegex*(buf: string, flags: int): Option[Regex] = var regex: Regex var error_msg_size = 64 diff --git a/src/types/cookie.nim b/src/types/cookie.nim index c848813d..e5e50d3e 100644 --- a/src/types/cookie.nim +++ b/src/types/cookie.nim @@ -21,7 +21,7 @@ type path {.jsget.}: string CookieJar* = ref object - filter: URLFilter + filter*: URLFilter cookies*: seq[Cookie] proc parseCookieDate(val: string): Option[DateTime] = @@ -109,6 +109,14 @@ 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) +# For debugging +proc `$`*(cookiejar: CookieJar): string = + result &= $cookiejar.filter + result &= "\n" + for cookie in cookiejar.cookies: + result &= "Cookie " + result &= $cookie[] + proc serialize*(cookiejar: CookieJar, location: URL): string = if not cookiejar.filter.match(location): return "" # fail |