about summary refs log tree commit diff stats
path: root/src/types/urimethodmap.nim
blob: eed8b11203baa1e3aa09b4b5f85e2ee847750849 (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
# w3m's URI method map format.

import std/strutils
import std/tables

import types/opt
import types/url
import utils/twtstr

type URIMethodMap* = object
  map*: Table[string, string]

func rewriteURL(pattern, surl: string): string =
  result = ""
  var was_perc = false
  for c in pattern:
    if was_perc:
      if c == '%':
        result &= '%'
      elif c == 's':
        result &= surl
      else:
        result &= '%'
        result &= c
      was_perc = false
    elif c != '%':
      result &= c
    else:
      was_perc = true
  if was_perc:
    result &= '%'

type URIMethodMapResult* = enum
  URI_RESULT_NOT_FOUND, URI_RESULT_SUCCESS, URI_RESULT_WRONG_URL

proc findAndRewrite*(this: URIMethodMap; url: var URL): URIMethodMapResult =
  let protocol = url.protocol
  if protocol in this.map:
    let surl = this.map[protocol].rewriteURL($url)
    let x = newURL(surl)
    if x.isNone:
      return URI_RESULT_WRONG_URL
    url = x.get
    return URI_RESULT_SUCCESS
  return URI_RESULT_NOT_FOUND

proc parseURIMethodMap*(this: var URIMethodMap; s: string) =
  for line in s.split('\n'):
    if line.len == 0 or line[0] == '#':
      continue # comments
    var k = ""
    var i = 0
    while i < line.len and line[i] notin AsciiWhitespace + {':'}:
      k &= line[i].toLowerAscii()
      inc i
    if i >= line.len or line[i] != ':':
      continue # invalid
    k &= ':'
    inc i # skip colon
    while i < line.len and line[i] in AsciiWhitespace:
      inc i
    var v = line.until(AsciiWhitespace, i)
    # Basic w3m compatibility.
    # If needed, w3m-cgi-compat covers more cases.
    if v.startsWith("file:/cgi-bin/"):
      v = "cgi-bin:" & v.substr("file:/cgi-bin/".len)
    elif v.startsWith("file:///cgi-bin/"):
      v = "cgi-bin:" & v.substr("file:///cgi-bin/".len)
    elif v.startsWith("/cgi-bin/"):
      v = "cgi-bin:" & v.substr("/cgi-bin/".len)
    discard this.map.hasKeyOrPut(k, v)

proc parseURIMethodMap*(s: string): URIMethodMap =
  result = URIMethodMap()
  result.parseURIMethodMap(s)

proc append*(this: var URIMethodMap; that: URIMethodMap) =
  for k, v in that.map:
    discard this.map.hasKeyOrPut(k, v)