about summary refs log tree commit diff stats
path: root/adapter/protocol/gopher.nim
blob: 218e2da494006c5882b3c78391f7082561091e96 (plain) (blame)
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
import std/options
import std/os
import std/posix
import std/strutils

import ../gophertypes
import lcgi

proc loadSearch(os: PosixStream; t: GopherType; surl: string) =
  os.sendDataLoop("""
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>
""")

proc loadRegular(os: PosixStream; t: GopherType; path: var string;
    host, port, query: string) =
  let ps = os.connectSocket(host, port)
  enterNetworkSandbox()
  if query != "":
    path &= '\t'
    path &= query
  path &= '\n'
  ps.sendDataLoop(percentDecode(path))
  let s = case t
  of gtDirectory, gtSearch: "Content-Type: text/gopher\n"
  of gtHTML: "Content-Type: text/html\n"
  of gtGif: "Content-Type: image/gif\n"
  of gtPng: "Content-Type: image/png\n"
  of gtTextFile, gtError: "Content-Type: text/plain\n"
  else: ""
  os.sendDataLoop(s & '\n')
  var buffer: array[4096, uint8]
  while true:
    let n = ps.recvData(buffer)
    if n == 0:
      break
    os.sendDataLoop(addr buffer[0], n)
  ps.sclose()

proc main() =
  let os = newPosixStream(STDOUT_FILENO)
  if getEnv("REQUEST_METHOD") != "GET":
    os.die("InvalidMethod")
  let scheme = getEnv("MAPPED_URI_SCHEME")
  var host = getEnv("MAPPED_URI_HOST")
  if host == "":
    os.die("InvalidURL missing hostname")
  if host[0] == '[' and host[^1] == ']':
    host.delete(0..0)
    host.setLen(host.high)
  let port = $parseInt32(getEnv("MAPPED_URI_PORT")).get(70)
  let query = getEnv("MAPPED_URI_QUERY").after('=')
  var path = getEnv("MAPPED_URI_PATH")
  var i = 0
  while i < path.len and path[i] == '/':
    inc i
  var t = gtDirectory
  if i < path.len:
    t = gopherType(path[i])
    if t != gtUnknown:
      path.delete(0 .. i)
    else:
      t = gtDirectory
  if t == gtSearch and query == "":
    os.loadSearch(t, scheme & "://" & host & ":" & port & '/')
  else:
    os.loadRegular(t, path, host, port, query)

main()