about summary refs log tree commit diff stats
path: root/src/loader
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-08-03 01:14:41 +0200
committerbptato <nincsnevem662@gmail.com>2024-08-03 01:54:35 +0200
commit4c64687290c908cd791a058dede9bd4f2a1c7757 (patch)
tree4e72720aa016320a02d19b4a051b9b9916b714f9 /src/loader
parent270cf870eb84e80f2de1f2be64b682849ca55585 (diff)
downloadchawan-4c64687290c908cd791a058dede9bd4f2a1c7757.tar.gz
loader: move back data URL handling
data URIs can get megabytes long; however, you can only stuff so many
bytes into the envp. (This was thwarting my efforts to view pandoc-
generated standalone HTML in Chawan.) So put `data:' back into the
loader process.
Diffstat (limited to 'src/loader')
-rw-r--r--src/loader/loader.nim51
-rw-r--r--src/loader/loaderhandle.nim4
2 files changed, 50 insertions, 5 deletions
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index fec07d99..91212e24 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -407,6 +407,49 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: LoaderHandle;
   else:
     handle.sendResult(ERROR_URL_NOT_IN_CACHE)
 
+# Data URL handler.
+# Moved back into loader from CGI, because data URLs can get extremely long
+# and thus no longer fit into the environment.
+proc loadDataSend(ctx: LoaderContext; handle: LoaderHandle; s, ct: string) =
+  handle.sendResult(0)
+  handle.sendStatus(200)
+  handle.sendHeaders(newHeaders({"Content-Type": ct}))
+  let buffer = newLoaderBuffer(size = s.len)
+  buffer.len = s.len
+  copyMem(buffer.page, unsafeAddr s[0], s.len)
+  let output = handle.output
+  case ctx.pushBuffer(output, buffer, 0)
+  of pbrUnregister:
+    if output.registered:
+      ctx.unregister(output)
+    output.oclose()
+  of pbrDone:
+    if output.registered or output.suspended:
+      output.istreamAtEnd = true
+      ctx.outputMap[output.ostream.fd] = output
+    else:
+      output.oclose()
+
+proc loadData(ctx: LoaderContext; handle: LoaderHandle; request: Request) =
+  let url = request.url
+  var ct = url.path.s.until(',')
+  if AllChars - Ascii + Controls - {'\t', ' '} in ct:
+    handle.sendResult(ERROR_INVALID_URL, "invalid data URL")
+    handle.close()
+    return
+  let sd = ct.len + 1 # data start
+  let body = percentDecode(url.path.s, sd)
+  if ct.endsWith(";base64"):
+    let d = atob0(body) # decode from ct end + 1
+    if d.isNone:
+      handle.sendResult(ERROR_INVALID_URL, "invalid data URL")
+      handle.close()
+      return
+    ct.setLen(ct.len - ";base64".len) # remove base64 indicator
+    ctx.loadDataSend(handle, d.get, ct)
+  else:
+    ctx.loadDataSend(handle, body, ct)
+
 proc loadResource(ctx: LoaderContext; client: ClientData;
     config: LoaderClientConfig; request: Request; handle: LoaderHandle) =
   var redo = true
@@ -452,15 +495,17 @@ proc loadResource(ctx: LoaderContext; client: ClientData;
       ctx.loadFromCache(client, handle, request)
       assert handle.istream == nil
       handle.close()
+    elif request.url.scheme == "data":
+      ctx.loadData(handle, request)
     else:
       prevurl = request.url
       case ctx.config.uriMethodMap.findAndRewrite(request.url)
-      of URI_RESULT_SUCCESS:
+      of ummrSuccess:
         inc tries
         redo = true
-      of URI_RESULT_WRONG_URL:
+      of ummrWrongURL:
         handle.rejectHandle(ERROR_INVALID_URI_METHOD_ENTRY)
-      of URI_RESULT_NOT_FOUND:
+      of ummrNotFound:
         handle.rejectHandle(ERROR_UNKNOWN_SCHEME)
   if tries >= MaxRewrites:
     handle.rejectHandle(ERROR_TOO_MANY_REWRITES)
diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim
index aa3a32d4..cb05efa1 100644
--- a/src/loader/loaderhandle.nim
+++ b/src/loader/loaderhandle.nim
@@ -93,9 +93,9 @@ func cap*(buffer: LoaderBuffer): int {.inline.} =
 template isEmpty*(output: OutputHandle): bool =
   output.currentBuffer == nil and not output.suspended
 
-proc newLoaderBuffer*(): LoaderBuffer =
+proc newLoaderBuffer*(size = LoaderBufferPageSize): LoaderBuffer =
   return LoaderBuffer(
-    page: cast[ptr UncheckedArray[uint8]](alloc(LoaderBufferPageSize)),
+    page: cast[ptr UncheckedArray[uint8]](alloc(size)),
     len: 0
   )
 
v1.6.1&id=1f9a86d1515416a03721be261ae8fc937f129e9d'>^
11ff42af ^
d8ea8d5f ^
0bc410c5 ^
698ba46a ^








ccd3f3c3 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100