about summary refs log tree commit diff stats
path: root/src/local
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-12 19:51:03 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-12 20:20:24 +0100
commit22480a38c618aea42285b20868231f247932f2ab (patch)
treeba9b562124c1c30782ed87cd94122e962b80f637 /src/local
parent232d861836993d81f7828a2917e8d242a23194e0 (diff)
downloadchawan-22480a38c618aea42285b20868231f247932f2ab.tar.gz
loader: remove applyHeaders
Better compute the values we need on-demand at the call sites; this way,
we can pass through content type attributes to mailcap too.

(Also, remove a bug where applyResponse was called twice.)
Diffstat (limited to 'src/local')
-rw-r--r--src/local/client.nim5
-rw-r--r--src/local/container.nim19
-rw-r--r--src/local/pager.nim37
3 files changed, 31 insertions, 30 deletions
diff --git a/src/local/client.nim b/src/local/client.nim
index 0d1bf063..6b605311 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -518,8 +518,9 @@ proc handleRead(client: Client, fd: int) =
     let response = stream.readResponse(container.request)
     if response.body == nil:
       client.pager.fail(container, response.getErrorMessage())
-    elif response.redirect != nil:
-      client.pager.redirect(container, response)
+    elif (let redirect = response.getRedirect(container.request);
+        redirect != nil):
+      client.pager.redirect(container, response, redirect)
       response.body.close()
     else:
       client.pager.connected(container, response)
diff --git a/src/local/container.nim b/src/local/container.nim
index 49d8885e..fc3384d9 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -1402,15 +1402,11 @@ proc applyResponse*(container: Container; response: Response) =
   container.setLoadInfo("Connected to " & $response.url & ". Downloading...")
   # setup content type; note that isSome means an override so we skip it
   if container.contentType.isNone:
-    if response.contentType == "application/octet-stream":
-      let contentType = guessContentType(container.url.pathname,
-        "application/octet-stream", container.config.mimeTypes)
-      if contentType != "application/octet-stream":
-        container.contentType = some(contentType)
-      else:
-        container.contentType = some(response.contentType)
-    else:
-      container.contentType = some(response.contentType)
+    var contentType = response.getContentType()
+    if contentType == "application/octet-stream":
+      contentType = container.config.mimeTypes
+        .guessContentType(container.url.pathname)
+    container.contentType = some(contentType)
   # setup charsets:
   # * override charset
   # * network charset
@@ -1418,8 +1414,9 @@ proc applyResponse*(container: Container; response: Response) =
   # HTML may override the last two (but not the override charset).
   if container.config.charsetOverride != CHARSET_UNKNOWN:
     container.charsetStack = @[container.config.charsetOverride]
-  elif response.charset != CHARSET_UNKNOWN:
-    container.charsetStack = @[response.charset]
+  elif (let charset = response.getCharset(CHARSET_UNKNOWN);
+      charset != CHARSET_UNKNOWN):
+    container.charsetStack = @[charset]
   else:
     container.charsetStack = @[]
     for i in countdown(container.config.charsets.high, 0):
diff --git a/src/local/pager.nim b/src/local/pager.nim
index cba5a5d3..a0f63aca 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -1087,11 +1087,10 @@ type CheckMailcapResult = object
   ishtml: bool
 
 # Pipe output of an x-ansioutput mailcap command to the text/x-ansi handler.
-proc ansiDecode(pager: Pager; url: URL; charset: Charset; ishtml: var bool;
-    fdin: cint): cint =
-  let entry = pager.mailcap.getMailcapEntry("text/x-ansi", "", url, charset)
+proc ansiDecode(pager: Pager; url: URL; ishtml: var bool; fdin: cint): cint =
+  let entry = pager.mailcap.getMailcapEntry("text/x-ansi", "", url)
   var canpipe = true
-  let cmd = unquoteCommand(entry.cmd, "text/x-ansi", "", url, charset, canpipe)
+  let cmd = unquoteCommand(entry.cmd, "text/x-ansi", "", url, canpipe)
   if not canpipe:
     pager.alert("Error: could not pipe to text/x-ansi, decoding as text/plain")
     return -1
@@ -1283,35 +1282,34 @@ proc filterBuffer(pager: Pager; stream: SocketStream; cmd: string;
 # pager is suspended until the command exits.
 #TODO add support for edit/compose, better error handling
 proc checkMailcap(pager: Pager; container: Container; stream: SocketStream;
-    istreamOutputId: int): CheckMailcapResult =
+    istreamOutputId: int; contentType: string): CheckMailcapResult =
   if container.filter != nil:
     return pager.filterBuffer(stream, container.filter.cmd, container.ishtml)
   # contentType must exist, because we set it in applyResponse
-  let contentType = container.contentType.get
-  if contentType == "text/html":
+  let shortContentType = container.contentType.get
+  if shortContentType == "text/html":
     # We support text/html natively, so it would make little sense to execute
     # mailcap filters for it.
     return CheckMailcapResult(connect: true, fdout: stream.fd, ishtml: true)
-  if contentType == "text/plain":
+  if shortContentType == "text/plain":
     # text/plain could potentially be useful. Unfortunately, many mailcaps
     # include a text/plain entry with less by default, so it's probably better
     # to ignore this.
     return CheckMailcapResult(connect: true, fdout: stream.fd)
   #TODO callback for outpath or something
   let url = container.url
-  let cs = container.charset
-  let entry = pager.mailcap.getMailcapEntry(contentType, "", url, cs)
+  let entry = pager.mailcap.getMailcapEntry(contentType, "", url)
   if entry == nil:
     return CheckMailcapResult(connect: true, fdout: stream.fd)
   let tmpdir = pager.tmpdir
   let ext = url.pathname.afterLast('.')
   let tempfile = getTempFile(tmpdir, ext)
   let outpath = if entry.nametemplate != "":
-    unquoteCommand(entry.nametemplate, contentType, tempfile, url, cs)
+    unquoteCommand(entry.nametemplate, contentType, tempfile, url)
   else:
     tempfile
   var canpipe = true
-  let cmd = unquoteCommand(entry.cmd, contentType, outpath, url, cs, canpipe)
+  let cmd = unquoteCommand(entry.cmd, contentType, outpath, url, canpipe)
   var ishtml = HTMLOUTPUT in entry.flags
   let needsterminal = NEEDSTERMINAL in entry.flags
   putEnv("MAILCAP_URL", $url)
@@ -1336,7 +1334,7 @@ proc checkMailcap(pager: Pager; container: Container; stream: SocketStream;
       pager.runMailcapReadFile(stream, cmd, outpath, pipefdOut)
     discard close(pipefdOut[1]) # close write
     let fdout = if not ishtml and ANSIOUTPUT in entry.flags:
-      pager.ansiDecode(url, cs, ishtml, pipefdOut[0])
+      pager.ansiDecode(url, ishtml, pipefdOut[0])
     else:
       pipefdOut[0]
     delEnv("MAILCAP_URL")
@@ -1368,10 +1366,10 @@ proc fail*(pager: Pager; container: Container; errorMessage: string) =
   else:
     pager.alert("Can't load " & $container.url & " (" & errorMessage & ")")
 
-proc redirect*(pager: Pager; container: Container; response: Response) =
+proc redirect*(pager: Pager; container: Container; response: Response;
+    request: Request) =
   # still need to apply response, or we lose cookie jars.
   container.applyResponse(response)
-  let request = response.redirect
   if container.redirectdepth < pager.config.network.max_redirect:
     if container.url.scheme == request.url.scheme or
         container.url.scheme == "cgi-bin" or
@@ -1395,10 +1393,15 @@ proc connected*(pager: Pager; container: Container; response: Response) =
     pager.authorize()
     istream.close()
     return
-  let mailcapRes = pager.checkMailcap(container, istream, response.outputId)
+  let realContentType = if "Content-Type" in response.headers:
+    response.headers["Content-Type"]
+  else:
+    # both contentType and charset must be set by applyResponse.
+    container.contentType.get & ";charset=" & $container.charset
+  let mailcapRes = pager.checkMailcap(container, istream, response.outputId,
+    realContentType)
   if mailcapRes.connect:
     container.ishtml = mailcapRes.ishtml
-    container.applyResponse(response)
     # buffer now actually exists; create a process for it
     container.process = pager.forkserver.forkBuffer(
       container.config,