about summary refs log tree commit diff stats
path: root/adapter
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-12-12 22:06:46 +0100
committerbptato <nincsnevem662@gmail.com>2023-12-12 22:07:07 +0100
commitbf761bcb6dcc5288a86aa5e8c2b67df3f0df056b (patch)
treea2f4c0d47ed484bcca4daaaa11b4d862243019fe /adapter
parent1df10adfe7eb20bc460eeb0e5a8e242970642c58 (diff)
downloadchawan-bf761bcb6dcc5288a86aa5e8c2b67df3f0df056b.tar.gz
Move gopher to adapter/
Also, move default urimethodmap config to res.
Diffstat (limited to 'adapter')
-rw-r--r--adapter/format/gopher2html.nim16
-rw-r--r--adapter/gophertypes.nim15
-rw-r--r--adapter/protocol/gopher.nim113
3 files changed, 129 insertions, 15 deletions
diff --git a/adapter/format/gopher2html.nim b/adapter/format/gopher2html.nim
index cfdeab1e..33cd564a 100644
--- a/adapter/format/gopher2html.nim
+++ b/adapter/format/gopher2html.nim
@@ -7,21 +7,7 @@ import std/strutils
 
 import utils/twtstr
 
-type GopherType = enum
-  UNKNOWN = "unsupported"
-  TEXT_FILE = "text file"
-  ERROR = "error"
-  DIRECTORY = "directory"
-  DOS_BINARY = "DOS binary"
-  SEARCH = "search"
-  MESSAGE = "message"
-  SOUND = "sound"
-  GIF = "gif"
-  HTML = "HTML"
-  INFO = ""
-  IMAGE = "image"
-  BINARY = "binary"
-  PNG = "png"
+include ../gophertypes
 
 func gopherType(c: char): GopherType =
   return case c
diff --git a/adapter/gophertypes.nim b/adapter/gophertypes.nim
new file mode 100644
index 00000000..dbc8d64d
--- /dev/null
+++ b/adapter/gophertypes.nim
@@ -0,0 +1,15 @@
+type GopherType = enum
+  UNKNOWN = "unsupported"
+  TEXT_FILE = "text file"
+  ERROR = "error"
+  DIRECTORY = "directory"
+  DOS_BINARY = "DOS binary"
+  SEARCH = "search"
+  MESSAGE = "message"
+  SOUND = "sound"
+  GIF = "gif"
+  HTML = "HTML"
+  INFO = ""
+  IMAGE = "image"
+  BINARY = "binary"
+  PNG = "png"
diff --git a/adapter/protocol/gopher.nim b/adapter/protocol/gopher.nim
new file mode 100644
index 00000000..cf3038f7
--- /dev/null
+++ b/adapter/protocol/gopher.nim
@@ -0,0 +1,113 @@
+import std/envvars
+import std/options
+
+import bindings/curl
+import loader/connecterror
+import loader/curlwrap
+import loader/request
+import types/opt
+import types/url
+import utils/twtstr
+
+include ../gophertypes
+
+type GopherHandle = ref object
+  curl: CURL
+  t: GopherType
+  statusline: bool
+
+func gopherType(c: char): GopherType =
+  return case c
+  of '0': TEXT_FILE
+  of '1': DIRECTORY
+  of '3': ERROR
+  of '5': DOS_BINARY
+  of '7': SEARCH
+  of 'm': MESSAGE
+  of 's': SOUND
+  of 'g': GIF
+  of 'h': HTML
+  of 'i': INFO
+  of 'I': IMAGE
+  of '9': BINARY
+  of 'p': PNG
+  else: UNKNOWN
+
+proc onStatusLine(op: GopherHandle) =
+  var status: clong
+  op.curl.getinfo(CURLINFO_RESPONSE_CODE, addr status)
+  stdout.write("Status: " & $status & "\n")
+  let s = case op.t
+  of DIRECTORY, SEARCH: "Content-Type: text/gopher\n"
+  of HTML: "Content-Type: text/html\n"
+  of GIF: "Content-Type: image/gif\n"
+  of PNG: "Content-Type: image/png\n"
+  of TEXT_FILE, ERROR: "Content-Type: text/plain\n"
+  else: ""
+  stdout.write(s & "\n")
+
+proc loadSearch(op: GopherHandle, surl: string) =
+  stdout.write("""
+Content-Type: text/html
+
+<!DOCTYPE HTML>
+<HTML>
+<HEAD>
+<BASE HREF="""" & surl & """">
+</HEAD>
+<BODY>
+<H1>Search """ & htmlEscape(surl) & """</H1>
+<FORM>
+<INPUT TYPE=SEARCH NAME="NAME">
+</FORM>
+</BODY>
+</HTML>
+""")
+
+# From the documentation: size is always 1.
+proc curlWriteBody(p: cstring, size, nmemb: csize_t, userdata: pointer):
+    csize_t {.cdecl.} =
+  let op = cast[GopherHandle](userdata)
+  if not op.statusline:
+    op.statusline = true
+    op.onStatusLine()
+  return csize_t(stdout.writeBuffer(p, int(nmemb)))
+
+proc main() =
+  let curl = curl_easy_init()
+  doAssert curl != nil
+  if getEnv("REQUEST_METHOD") != "GET":
+    stdout.write("Cha-Control: ConnectionError " & $int(ERROR_INVALID_METHOD))
+    return
+  var url = newURL(getEnv("QUERY_STRING")).get
+  var path = url.pathname
+  if path.len < 1:
+    path &= '/'
+  if path.len < 2:
+    path &= '1'
+    url = newURL(url)
+    url.setPathname(path)
+  let op = GopherHandle(
+    curl: curl,
+    t: gopherType(path[1])
+  )
+  if op.t == SEARCH:
+    if url.query.isNone:
+      op.loadSearch(url.serialize())
+      return
+    else:
+      url.query = some(url.query.get.after('='))
+  let surl = url.serialize()
+  #TODO avoid re-parsing
+  curl.setopt(CURLOPT_URL, surl)
+  curl.setopt(CURLOPT_WRITEDATA, op)
+  curl.setopt(CURLOPT_WRITEFUNCTION, curlWriteBody)
+  let proxy = getEnv("ALL_PROXY")
+  if proxy != "":
+    curl.setopt(CURLOPT_PROXY, proxy)
+  let res = curl_easy_perform(curl)
+  if res != CURLE_OK and not op.statusline:
+    stdout.write("Cha-Control: ConnectionError " & $int(res) & "\n")
+  curl_easy_cleanup(curl)
+
+main()
@lavabit.com> 2010-01-18 17:22:02 +0100 committer hut <hut@lavabit.com> 2010-01-18 17:22:02 +0100 actions: bookmark old dir in ` when using :cd' href='/akspecs/ranger/commit/TODO?h=v1.6.1&id=2c1d2db0894cd9578bbd9665dee71ae984131208'>2c1d2db0 ^
291ca616 ^
50845f37 ^
039c03ef ^
af6658b3 ^
efe2d7a3 ^
f0df3fa5 ^
a986e2bd ^

3fe38754 ^

6a8d5d23 ^
aad61455 ^
7a268c8b ^

efdc7b16 ^
4be8b401 ^



d955e3f0 ^
75013dc7 ^
67bb838c ^
a808a661 ^
bba8d293 ^
2a64495f ^
5e449699 ^
fc486c60 ^
c5450bd1 ^
7b04e507 ^
87db0130 ^
dd4a4145 ^
8f2f1767 ^
db1721dd ^
aea5cf92 ^
b624bd94 ^
69d1220f ^
bd8ef764 ^
0128bee7 ^
6f43de0a ^




fca1fc4f ^
f70ee6b2 ^
0db4c9b2 ^
b2d63ef5 ^
291ca616 ^
d994d0d6 ^
01c89bb5 ^
66c5bb93 ^
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