about summary refs log tree commit diff stats
path: root/src/loader
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-16 18:24:42 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-16 18:25:24 +0100
commita83c0be8abb07e736297dcc6d6304bfbb243eb99 (patch)
treef118e60b4da3ce625155d1bd1394effe983ba4b4 /src/loader
parent1d2b576e408059f500e97e52e8930d2cb7c38551 (diff)
downloadchawan-a83c0be8abb07e736297dcc6d6304bfbb243eb99.tar.gz
pager, loader: add "Save file to" functionality
As simple as it could be; no download panel yet.

Also, remove the xdg-open default mailcap entry; it's better to just
save by default.
Diffstat (limited to 'src/loader')
-rw-r--r--src/loader/loader.nim72
1 files changed, 53 insertions, 19 deletions
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index 3040c579..fdc87eb2 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -75,6 +75,7 @@ type
     lcAddClient
     lcLoad
     lcPassFd
+    lcRedirectToFile
     lcRemoveCachedItem
     lcRemoveClient
     lcResume
@@ -202,38 +203,45 @@ proc getOutputId(ctx: LoaderContext): int =
   result = ctx.outputNum
   inc ctx.outputNum
 
-type AddCacheFileResult = tuple[outputId: int; cacheFile: string]
-
-proc addCacheFile(ctx: LoaderContext; client: ClientData; output: OutputHandle):
-    AddCacheFileResult =
-  if output.parent != nil and output.parent.cacheId != -1:
-    # may happen e.g. if client tries to cache a `cache:' URL
-    return (output.parent.cacheId, "") #TODO can we get the file name somehow?
-  let tmpf = getTempFile(ctx.config.tmpdir)
-  let ps = newPosixStream(tmpf, O_CREAT or O_WRONLY, 0o600)
-  if unlikely(ps == nil):
-    return (-1, "")
+proc redirectToFile(ctx: LoaderContext; output: OutputHandle;
+    targetPath: string): bool =
+  let ps = newPosixStream(targetPath, O_CREAT or O_WRONLY, 0o600)
+  if ps == nil:
+    return false
   if output.currentBuffer != nil:
     let n = ps.sendData(output.currentBuffer, output.currentBufferIdx)
     if unlikely(n < output.currentBuffer.len - output.currentBufferIdx):
       ps.close()
-      return (-1, "")
+      return false
   for buffer in output.buffers:
     let n = ps.sendData(buffer)
     if unlikely(n < buffer.len):
       ps.close()
-      return (-1, "")
-  let cacheId = output.outputId
+      return false
   if output.parent != nil:
-    output.parent.cacheId = cacheId
     output.parent.outputs.add(OutputHandle(
       parent: output.parent,
       ostream: ps,
       istreamAtEnd: output.istreamAtEnd,
       outputId: ctx.getOutputId()
     ))
-  client.cacheMap.add(CachedItem(id: cacheId, path: tmpf, refc: 1))
-  return (cacheId, tmpf)
+  return true
+
+type AddCacheFileResult = tuple[outputId: int; cacheFile: string]
+
+proc addCacheFile(ctx: LoaderContext; client: ClientData; output: OutputHandle):
+    AddCacheFileResult =
+  if output.parent != nil and output.parent.cacheId != -1:
+    # may happen e.g. if client tries to cache a `cache:' URL
+    return (output.parent.cacheId, "") #TODO can we get the file name somehow?
+  let tmpf = getTempFile(ctx.config.tmpdir)
+  if ctx.redirectToFile(output, tmpf):
+    let cacheId = output.outputId
+    if output.parent != nil:
+      output.parent.cacheId = cacheId
+    client.cacheMap.add(CachedItem(id: cacheId, path: tmpf, refc: 1))
+    return (cacheId, tmpf)
+  return (-1, "")
 
 proc addFd(ctx: LoaderContext; handle: LoaderHandle) =
   let output = handle.output
@@ -493,6 +501,18 @@ proc addCacheFile(ctx: LoaderContext; stream: SocketStream) =
   stream.swrite(file)
   stream.close()
 
+proc redirectToFile(ctx: LoaderContext; stream: SocketStream) =
+  var outputId: int
+  var targetPath: string
+  stream.sread(outputId)
+  stream.sread(targetPath)
+  let output = ctx.findOutput(outputId)
+  var success = false
+  if output != nil:
+    success = ctx.redirectToFile(output, targetPath)
+  stream.swrite(success)
+  stream.close()
+
 proc shareCachedItem(ctx: LoaderContext; stream: SocketStream) =
   # share a cached file with another buffer. this is for newBufferFrom
   # (i.e. view source)
@@ -606,6 +626,9 @@ proc acceptConnection(ctx: LoaderContext) =
     of lcPassFd:
       privileged_command
       ctx.passFd(stream)
+    of lcRedirectToFile:
+      privileged_command
+      ctx.redirectToFile(stream)
     of lcRemoveCachedItem:
       ctx.removeCachedItem(stream, client)
     of lcLoad:
@@ -884,6 +907,17 @@ proc addCacheFile*(loader: FileLoader; outputId, targetPid: int):
   stream.sread(cacheFile)
   return (outputId, cacheFile)
 
+proc redirectToFile*(loader: FileLoader; outputId: int; targetPath: string):
+    bool =
+  let stream = loader.connect()
+  if stream == nil:
+    return false
+  stream.swrite(lcRedirectToFile)
+  stream.swrite(outputId)
+  stream.swrite(targetPath)
+  stream.flush()
+  stream.sread(result)
+
 const BufferSize = 4096
 
 proc handleHeaders(response: Response; request: Request; stream: SocketStream) =
@@ -994,11 +1028,11 @@ proc passFd*(loader: FileLoader; id: string; fd: FileHandle) =
     stream.sendFileHandle(fd)
     stream.close()
 
-proc removeCachedItem*(loader: FileLoader; outputId: int) =
+proc removeCachedItem*(loader: FileLoader; cacheId: int) =
   let stream = loader.connect()
   if stream != nil:
     stream.swrite(lcRemoveCachedItem)
-    stream.swrite(outputId)
+    stream.swrite(cacheId)
     stream.close()
 
 proc addClient*(loader: FileLoader; key: ClientKey; pid: int;