about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/loader/connecterror.nim2
-rw-r--r--src/loader/loader.nim66
-rw-r--r--src/loader/loaderhandle.nim7
-rw-r--r--src/local/pager.nim7
-rw-r--r--src/local/term.nim2
5 files changed, 41 insertions, 43 deletions
diff --git a/src/loader/connecterror.nim b/src/loader/connecterror.nim
index 1ee4e48b..5b428526 100644
--- a/src/loader/connecterror.nim
+++ b/src/loader/connecterror.nim
@@ -1,4 +1,5 @@
 type ConnectionError* = enum
+  ceCGICachedBodyUnavailable = -18
   ceCGIOutputHandleNotFound = -17
   ceCGIFailedToOpenCacheOutput = -16
   ceCGICachedBodyNotFound = -15
@@ -30,6 +31,7 @@ type ConnectionError* = enum
   ceProxyInvalidResponse = (11, "ProxyInvalidResponse")
 
 const ErrorMessages* = [
+  ceCGICachedBodyUnavailable: "request body is not ready in the cache",
   ceCGIOutputHandleNotFound: "request body output handle not found",
   ceCGIFailedToOpenCacheOutput: "failed to open cache output",
   ceCGICachedBodyNotFound: "cached request body not found",
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index 9ebc6917..c0464789 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -52,12 +52,6 @@ import types/url
 import utils/twtstr
 
 type
-  CachedItem = ref object
-    id: int
-    refc: int
-    offset: int
-    path: string
-
   ClientData = ref object
     pid: int
     key: ClientKey
@@ -242,39 +236,12 @@ proc addCacheFile(ctx: LoaderContext; client: ClientData; output: OutputHandle):
     return cacheId
   return -1
 
-proc findOffset(ps: PosixStream): int =
-  try:
-    var buffer = default(array[512, char])
-    var off = 0
-    var lf = 1u # we start at EOL
-    while true:
-      let n = ps.recvData(buffer)
-      if n == 0:
-        return off
-      for i in 0 ..< n:
-        let c = buffer[i]
-        if c == '\n':
-          inc lf
-          if lf == 2:
-            return off + i + 1
-        elif c != '\r':
-          lf = 0
-      off += n
-  except IOError:
-    discard
-  return -1
-
 proc openCachedItem(client: ClientData; id: int): (PosixStream, int) =
   let n = client.cacheMap.find(id)
   if n != -1:
     let item = client.cacheMap[n]
     let ps = newPosixStream(client.cacheMap[n].path, O_RDONLY, 0)
-    if item.offset == -1:
-      let offset = ps.findOffset()
-      if offset == -1:
-        client.cacheMap.del(n)
-        return (nil, -1)
-      item.offset = offset
+    assert item.offset != -1
     ps.seek(item.offset)
     return (ps, n)
   return (nil, -1)
@@ -424,7 +391,27 @@ proc parseHeaders(handle: InputHandle; buffer: LoaderBuffer): int =
     return -1
 
 proc finishParse(handle: InputHandle) =
-  discard handle.parseHeaders(nil)
+  if handle.cacheRef != nil:
+    assert handle.cacheRef.offset == -1
+    let ps = newPosixStream(handle.cacheRef.path, O_RDONLY, 0)
+    if ps != nil:
+      var buffer {.noinit.}: array[4096, char]
+      var off = 0
+      while true:
+        let n = ps.recvData(buffer)
+        if n == 0:
+          break
+        let pn = handle.parseHeaders0(buffer.toOpenArray(0, n - 1))
+        if pn == -1:
+          break
+        off += pn
+        if pn < n:
+          handle.parser = nil
+          break
+      handle.cacheRef.offset = off
+      handle.cacheRef = nil
+  if handle.parser != nil:
+    discard handle.parseHeaders(nil)
 
 type HandleReadResult = enum
   hrrDone, hrrUnregister, hrrBrokenPipe
@@ -616,12 +603,14 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
       handle.sendResult(ceCGIFailedToOpenCacheOutput)
       return
     let cacheId = handle.output.outputId # welp
-    client.cacheMap.add(CachedItem(
+    let item = CachedItem(
       id: cacheId,
       path: tmpf,
       refc: 1,
       offset: -1
-    ))
+    )
+    handle.cacheRef = item
+    client.cacheMap.add(item)
   # Pipe the request body as stdin for POST.
   var istream: PosixStream = nil # child end (read)
   var ostream: PosixStream = nil # parent end (write)
@@ -636,6 +625,9 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
       return
     cachedHandle = ctx.findCachedHandle(request.body.cacheId)
     if cachedHandle != nil: # cached item still open, switch to streaming mode
+      if client.cacheMap[n].offset == -1:
+        handle.sendResult(ceCGICachedBodyUnavailable)
+        return
       istream2 = istream
   elif request.body.t == rbtOutput:
     outputIn = ctx.findOutput(request.body.outputId, client)
diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim
index b43149fb..4813d55d 100644
--- a/src/loader/loaderhandle.nim
+++ b/src/loader/loaderhandle.nim
@@ -17,6 +17,12 @@ type
     page*: ptr UncheckedArray[uint8]
     len*: int
 
+  CachedItem* = ref object
+    id*: int
+    refc*: int
+    offset*: int
+    path*: string
+
   LoaderBuffer* = ref LoaderBufferObj
 
   LoaderHandle* = ref object of RootObj
@@ -28,6 +34,7 @@ type
   InputHandle* = ref object of LoaderHandle
     outputs*: seq[OutputHandle] # list of outputs to be streamed into
     cacheId*: int # if cached, our ID in a client cacheMap
+    cacheRef*: CachedItem # if this is a tocache handle, a ref to our cache item
     parser*: HeaderParser # only exists for CGI handles
     rstate: ResponseState # track response state
 
diff --git a/src/local/pager.nim b/src/local/pager.nim
index f623bf06..b3602ad6 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -632,11 +632,8 @@ proc loadCachedImage(pager: Pager; container: Container; image: PosBitmap;
       cachedImage.data = blob
       cachedImage.state = cisLoaded
       cachedImage.cacheId = cacheId
-      if imageMode == imSixel and 4 < blob.size:
-        #TODO this should be a response header, but loader can't send us
-        # those yet...
-        let u = cast[ptr UncheckedArray[uint8]](blob.buffer)[4]
-        cachedImage.transparent = u == 1
+      let trns = response.headers.getOrDefault("Cha-Image-Sixel-Transparent", "0")
+      cachedImage.transparent = trns == "1"
     )
   )
   container.cachedImages.add(cachedImage)
diff --git a/src/local/term.nim b/src/local/term.nim
index 2e0b1e25..822c513d 100644
--- a/src/local/term.nim
+++ b/src/local/term.nim
@@ -822,7 +822,7 @@ proc outputSixelImage(term: Terminal; x, y: int; image: CanvasImage;
   # set raster attributes
   outs &= "\"1;1;" & $realw & ';' & $realh
   term.write(outs)
-  term.write(data.toOpenArray(5, preludeLen - 1))
+  term.write(data.toOpenArray(4, preludeLen - 1))
   let lookupTableLen = int(data.getU32BE(data.len - 4))
   let L = data.len - lookupTableLen - 4
   # Note: we only crop images when it is possible to do so in near constant