diff options
author | bptato <nincsnevem662@gmail.com> | 2024-05-11 19:56:25 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-05-11 20:06:10 +0200 |
commit | b8345d19efdecb27139e011e92f89efbb7618c08 (patch) | |
tree | 5d0f3de089ef40f1f653ee386771e326f9847cd6 /src/local | |
parent | 2c1d1899e424c5e055214d3647979f7f0ba4dcfe (diff) | |
download | chawan-b8345d19efdecb27139e011e92f89efbb7618c08.tar.gz |
buffer: fix multipart forms
* fix enctype not getting picked up * fix form data constructor requiring open() syscall (which gets blocked by our seccomp filter) * add closing boundary to multipart end * pass fds instead of path names through WebFile/Blob and send those through bufwriter/bufreader
Diffstat (limited to 'src/local')
-rw-r--r-- | src/local/client.nim | 11 | ||||
-rw-r--r-- | src/local/container.nim | 40 | ||||
-rw-r--r-- | src/local/pager.nim | 18 |
3 files changed, 46 insertions, 23 deletions
diff --git a/src/local/client.nim b/src/local/client.nim index af5e89a0..dc79438e 100644 --- a/src/local/client.nim +++ b/src/local/client.nim @@ -658,11 +658,12 @@ proc clientLoadJSModule(ctx: JSContext; module_name: cstringConst; JS_ThrowTypeError(ctx, "Failed to open file %s", module_name) return nil -proc readBlob(client: Client; path: string): Option[WebFile] {.jsfunc.} = - try: - return some(newWebFile(path)) - except IOError: - discard +proc readBlob(client: Client; path: string): WebFile {.jsfunc.} = + let ps = newPosixStream(path, O_RDONLY, 0) + if ps == nil: + return nil + let name = path.afterLast('/') + return newWebFile(name, ps.fd) #TODO this is dumb proc readFile(client: Client; path: string): string {.jsfunc.} = diff --git a/src/local/container.nim b/src/local/container.nim index 502b1de1..5b593f2a 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -7,6 +7,7 @@ import std/unicode import config/config import config/mimetypes +import io/bufstream import io/dynstream import io/promise import io/serversocket @@ -46,8 +47,8 @@ type setxsave: bool ContainerEventType* = enum - cetAnchor, cetNoAnchor, cetUpdate, cetReadLine, cetReadArea, cetOpen, - cetSetLoadInfo, cetStatus, cetAlert, cetLoaded, cetTitle, cetCancel + cetAnchor, cetNoAnchor, cetUpdate, cetReadLine, cetReadArea, cetReadFile, + cetOpen, cetSetLoadInfo, cetStatus, cetAlert, cetLoaded, cetTitle, cetCancel ContainerEvent* = object case t*: ContainerEventType @@ -1483,8 +1484,12 @@ proc readCanceled*(container: Container) = if repaint: container.needslines = true) -proc readSuccess*(container: Container; s: string) = - container.iface.readSuccess(s).then(proc(res: ReadSuccessResult) = +proc readSuccess*(container: Container; s: string; fd = -1) = + let p = container.iface.readSuccess(s, fd != -1) + if fd != -1: + container.iface.stream.reallyFlush() + SocketStream(container.iface.stream.source).sendFileHandle(FileHandle(fd)) + p.then(proc(res: ReadSuccessResult) = if res.repaint: container.needslines = true if res.open.isSome: @@ -1521,19 +1526,21 @@ proc onclick(container: Container; res: ClickResult; save: bool) = container.displaySelect(res.select.get) if res.readline.isSome: let rl = res.readline.get - let event = if rl.area: - ContainerEvent( - t: cetReadArea, - tvalue: rl.value - ) - else: - ContainerEvent( + case rl.t + of rltText: + container.triggerEvent(ContainerEvent( t: cetReadLine, prompt: rl.prompt, value: rl.value, password: rl.hide - ) - container.triggerEvent(event) + )) + of rltArea: + container.triggerEvent(ContainerEvent( + t: cetReadArea, + tvalue: rl.value + )) + of rltFile: + container.triggerEvent(ContainerEvent(t: cetReadFile)) proc click*(container: Container) {.jsfunc.} = if container.select.open: @@ -1601,10 +1608,9 @@ func hoverImage(container: Container): string {.jsfget.} = return container.hoverText[htImage] proc handleCommand(container: Container) = - var packetid, len: int - container.iface.stream.recvDataLoop(addr len, sizeof(len)) - container.iface.stream.recvDataLoop(addr packetid, sizeof(packetid)) - container.iface.resolve(packetid, len - sizeof(packetid)) + var packet: array[3, int] # 0 len, 1 auxLen, 2 packetid + container.iface.stream.recvDataLoop(addr packet[0], sizeof(packet)) + container.iface.resolve(packet[2], packet[0] - sizeof(packet[2]), packet[1]) proc startLoad(container: Container) = container.iface.load().then(proc(res: int) = diff --git a/src/local/pager.nim b/src/local/pager.nim index 93bf562c..c1bd18c0 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -65,6 +65,7 @@ type lmISearchB = "?" lmGotoLine = "Goto line: " lmDownload = "(Download)Save file to: " + lmBufferFile = "(Upload)Filename: " # fdin is the original fd; fdout may be the same, or different if mailcap # is used. @@ -1173,6 +1174,19 @@ proc updateReadLine*(pager: Pager) = if pager.commandMode: pager.command() of lmBuffer: pager.container.readSuccess(lineedit.news) + of lmBufferFile: + let ps = newPosixStream(lineedit.news, O_RDONLY, 0) + if ps == nil: + pager.alert("File not found") + pager.container.readCanceled() + else: + var stats: Stat + if fstat(ps.fd, stats) < 0 or S_ISDIR(stats.st_mode): + pager.alert("Not a file: " & lineedit.news) + else: + let name = lineedit.news.afterLast('/') + pager.container.readSuccess(name, ps.fd) + ps.sclose() of lmSearchF, lmSearchB: if lineedit.news != "": let regex = pager.compileSearchRegex(lineedit.news) @@ -1655,7 +1669,6 @@ proc connected(pager: Pager; container: Container; response: Response) = container.process = pager.forkserver.forkBuffer( container.config, container.url, - container.request, attrs, mailcapRes.ishtml, container.charsetStack @@ -1768,6 +1781,9 @@ proc handleEvent0(pager: Pager; container: Container; event: ContainerEvent): else: pager.container.readCanceled() pager.redraw = true + of cetReadFile: + if container == pager.container: + pager.setLineEdit(lmBufferFile, "") of cetOpen: let url = event.request.url if not event.save and (pager.container != container or |