diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-12 20:35:30 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-12 20:36:39 +0100 |
commit | a2eadfb39099b2e8bfd543f00d75b64916931959 (patch) | |
tree | 3df7afbb5a75ee51c1503b7961e940a3f37962a2 /src | |
parent | 8e6783a45fba48dd8f63fe7486e4691f05220b52 (diff) | |
download | chawan-a2eadfb39099b2e8bfd543f00d75b64916931959.tar.gz |
Add pager.externFilterSource
useful for filtering stuff through commands like rdrview
Diffstat (limited to 'src')
-rw-r--r-- | src/html/dom.nim | 2 | ||||
-rw-r--r-- | src/loader/loader.nim | 18 | ||||
-rw-r--r-- | src/local/container.nim | 4 | ||||
-rw-r--r-- | src/local/pager.nim | 68 | ||||
-rw-r--r-- | src/server/buffer.nim | 9 |
5 files changed, 85 insertions, 16 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim index c5140759..70f907c5 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -3435,7 +3435,7 @@ proc fetchClassicScript(element: HTMLScriptElement, url: URL, return let loader = window.loader.get let request = createPotentialCORSRequest(url, RequestDestination.SCRIPT, cors) - let response = loader.doRequest(request, canredir = false) + let response = loader.doRequest(request) if response.res != 0: element.onComplete(ScriptResult(t: RESULT_NULL)) return diff --git a/src/loader/loader.nim b/src/loader/loader.nim index 0755d427..6183e771 100644 --- a/src/loader/loader.nim +++ b/src/loader/loader.nim @@ -233,7 +233,7 @@ proc loadResource(ctx: LoaderContext, request: Request, handle: LoaderHandle) = handle.rejectHandle(ERROR_TOO_MANY_REWRITES) proc loadFromCache(ctx: LoaderContext, stream: SocketStream, request: Request) = - let handle = newLoaderHandle(stream, false, request.clientId) + let handle = newLoaderHandle(stream, request.canredir, request.clientId) let surl = $request.url let cachedHandle = ctx.findCachedHandle(surl) ctx.cacheMap.withValue(surl, p): @@ -270,6 +270,17 @@ proc loadFromCache(ctx: LoaderContext, stream: SocketStream, request: Request) = output.parent = cachedHandle cachedHandle.outputs.add(output) ctx.outputMap[output.ostream.fd] = output + if handle.outputs.len > 0: + let output = handle.output + if output.sostream != nil: + try: + handle.output.sostream.swrite(true) + except IOError: + # ignore error, that just means the buffer has already closed the + # stream + discard + output.sostream.close() + output.sostream = nil handle.close() proc onLoad(ctx: LoaderContext, stream: SocketStream) = @@ -794,12 +805,9 @@ proc onError*(loader: FileLoader, fd: int) = buffer[].buf = "" response.unregisterFun() -proc doRequest*(loader: FileLoader, request: Request, canredir = false): - Response = +proc doRequest*(loader: FileLoader, request: Request): Response = let response = Response(url: request.url) let stream = connectSocketStream(loader.process, false, blocking = true) - if canredir: - request.canredir = true #TODO set this somewhere else? request.clientId = (loader.clientPid, int(stream.fd)) stream.swrite(LOAD) stream.swrite(request) diff --git a/src/local/container.nim b/src/local/container.nim index 585c8a3f..9af35c63 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -85,6 +85,9 @@ type x: int y: int + BufferFilter* = ref object + cmd*: string + Container* = ref object parent* {.jsget.}: Container children* {.jsget.}: seq[Container] @@ -125,6 +128,7 @@ type jumpMark: PagePos marks: Table[string, PagePos] ishtml*: bool + filter*: BufferFilter jsDestructor(Highlight) jsDestructor(Container) diff --git a/src/local/pager.nim b/src/local/pager.nim index 3233b012..41ecb6a5 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -919,13 +919,26 @@ proc externInto(pager: Pager, cmd, ins: string): bool {.jsfunc.} = pager.setEnvVars() return runProcessInto(cmd, ins) +proc externFilterSource(pager: Pager, cmd: string, c: Container = nil, + contentType = opt(string)) {.jsfunc.} = + let container = newBufferFrom( + pager.forkserver, + pager.attrs, + if c != nil: c else: pager.container, + contentType.get(pager.container.contentType.get("")) + ) + pager.addContainer(container) + container.filter = BufferFilter(cmd: cmd) + proc authorize(pager: Pager) = pager.setLineEdit("Username: ", USERNAME) +type CheckMailcapResult = tuple[promise: EmptyPromise, connect: bool] + # Pipe input into the mailcap command, then read its output into a buffer. # needsterminal is ignored. proc runMailcapReadPipe(pager: Pager, container: Container, - entry: MailcapEntry, cmd: string): (EmptyPromise, bool) = + entry: MailcapEntry, cmd: string): CheckMailcapResult = var pipefd_in: array[2, cint] if pipe(pipefd_in) == -1: raise newException(Defect, "Failed to open pipe.") @@ -969,7 +982,7 @@ proc runMailcapReadPipe(pager: Pager, container: Container, # Pipe input into the mailcap command, and discard its output. # If needsterminal, leave stderr and stdout open and wait for the process. proc runMailcapWritePipe(pager: Pager, container: Container, - entry: MailcapEntry, cmd: string): (EmptyPromise, bool) = + entry: MailcapEntry, cmd: string): CheckMailcapResult = let needsterminal = NEEDSTERMINAL in entry.flags var pipefd: array[2, cint] if pipe(pipefd) == -1: @@ -1008,7 +1021,7 @@ proc runMailcapWritePipe(pager: Pager, container: Container, # new buffer. # needsterminal is ignored. proc runMailcapReadFile(pager: Pager, container: Container, - entry: MailcapEntry, cmd, outpath: string): (EmptyPromise, bool) = + entry: MailcapEntry, cmd, outpath: string): CheckMailcapResult = let fd = open(outpath, O_WRONLY or O_CREAT, 0o600) if fd == -1: return (nil, false) @@ -1042,7 +1055,7 @@ proc runMailcapReadFile(pager: Pager, container: Container, # Save input in a file, run the command, and discard its output. # If needsterminal, leave stderr and stdout open and wait for the process. proc runMailcapWriteFile(pager: Pager, container: Container, - entry: MailcapEntry, cmd, outpath: string): (EmptyPromise, bool) = + entry: MailcapEntry, cmd, outpath: string): CheckMailcapResult = let needsterminal = NEEDSTERMINAL in entry.flags let fd = open(outpath, O_WRONLY or O_CREAT, 0o600) if fd == -1: @@ -1069,9 +1082,50 @@ proc runMailcapWriteFile(pager: Pager, container: Container, ) return (p, false) +proc filterBuffer(pager: Pager, container: Container): CheckMailcapResult = + pager.setEnvVars() + let cmd = container.filter.cmd + var pipefd_in: array[2, cint] + if pipe(pipefd_in) == -1: + raise newException(Defect, "Failed to open pipe.") + var pipefd_out: array[2, cint] + if pipe(pipefd_out) == -1: + raise newException(Defect, "Failed to open pipe.") + let pid = fork() + if pid == -1: + return (nil, true) + elif pid == 0: + # child + discard close(pipefd_in[1]) + discard close(pipefd_out[0]) + stdout.flushFile() + discard dup2(pipefd_in[0], stdin.getFileHandle()) + discard dup2(pipefd_out[1], stdout.getFileHandle()) + let devnull = open("/dev/null", O_WRONLY) + discard dup2(devnull, stderr.getFileHandle()) + discard close(devnull) + discard close(pipefd_in[0]) + discard close(pipefd_out[1]) + discard execCmd(cmd) + quit(0) + else: + # parent + discard close(pipefd_in[0]) + discard close(pipefd_out[1]) + let fdin = pipefd_in[1] + let fdout = pipefd_out[0] + let p = container.redirectToFd(fdin, wait = false, cache = false) + let p2 = p.then(proc(): auto = + discard close(fdin) + return container.readFromFd(fdout, $pid, container.ishtml) + ).then(proc() = + discard close(fdout) + ) + return (p2, true) + # Search for a mailcap entry, and if found, execute the specified command # and pipeline the input and output appropriately. -# There is four possible outcomes: +# There are four possible outcomes: # * pipe stdin, discard stdout # * pipe stdin, read stdout # * write to file, run, discard stdout @@ -1080,7 +1134,9 @@ proc runMailcapWriteFile(pager: Pager, container: Container, # pager is suspended until the command exits. #TODO add support for edit/compose, better error handling (use Promise[bool] # instead of tuple[EmptyPromise, bool]) -proc checkMailcap(pager: Pager, container: Container): (EmptyPromise, bool) = +proc checkMailcap(pager: Pager, container: Container): CheckMailcapResult = + if container.filter != nil: + return pager.filterBuffer(container) if container.contentType.isNone: return (nil, true) let contentType = container.contentType.get diff --git a/src/server/buffer.nim b/src/server/buffer.nim index af857928..19a1407b 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -713,7 +713,7 @@ proc rewind(buffer: Buffer): bool = if buffer.loader.rewind(buffer.fd): return true let request = newRequest(buffer.url, fromcache = true) - let response = buffer.loader.doRequest(request, canredir = false) + let response = buffer.loader.doRequest(request) if response.body != nil: buffer.selector.unregister(buffer.fd) buffer.loader.unregistered.add(buffer.fd) @@ -781,7 +781,8 @@ proc connect*(buffer: Buffer): ConnectResult {.proxy.} = var cookies: seq[Cookie] var referrerpolicy: Option[ReferrerPolicy] let request = source.request - let response = buffer.loader.doRequest(request, canredir = true) + request.canredir = true #TODO set somewhere else? + let response = buffer.loader.doRequest(request) if response.body == nil: return ConnectResult( code: response.res, @@ -820,7 +821,7 @@ proc connect*(buffer: Buffer): ConnectResult {.proxy.} = # * connect2, telling loader to load at last (we block loader until then) # * redirectToFd, telling loader to load into the passed fd proc connect2*(buffer: Buffer) {.proxy.} = - if not buffer.source.request.fromcache: + if buffer.source.request.canredir: # Notify loader that we can proceed with loading the input stream. buffer.istream.swrite(false) buffer.istream.swrite(true) @@ -856,7 +857,7 @@ proc readFromFd*(buffer: Buffer, url: URL, ishtml: bool) {.proxy.} = charset: buffer.source.charset ) buffer.setHTML(ishtml) - let response = buffer.loader.doRequest(request, canredir = false) + let response = buffer.loader.doRequest(request) buffer.istream = response.body buffer.fd = int(response.body.source.getFd()) buffer.selector.registerHandle(buffer.fd, {Read}, 0) |