summary refs log tree commit diff stats
path: root/tests/deps/jester-#head/jester/private/utils.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/deps/jester-#head/jester/private/utils.nim')
-rw-r--r--tests/deps/jester-#head/jester/private/utils.nim195
1 files changed, 195 insertions, 0 deletions
diff --git a/tests/deps/jester-#head/jester/private/utils.nim b/tests/deps/jester-#head/jester/private/utils.nim
new file mode 100644
index 000000000..4b00c52a1
--- /dev/null
+++ b/tests/deps/jester-#head/jester/private/utils.nim
@@ -0,0 +1,195 @@
+# Copyright (C) 2012 Dominik Picheta
+# MIT License - Look at license.txt for details.
+import parseutils, strtabs, strutils, tables, net, mimetypes, asyncdispatch, os
+from cgi import decodeUrl
+
+const
+  useHttpBeast* = not defined(windows) and not defined(useStdLib)
+
+type
+  MultiData* = OrderedTable[string, tuple[fields: StringTableRef, body: string]]
+
+  Settings* = ref object
+    staticDir*: string # By default ./public
+    appName*: string
+    mimes*: MimeDb
+    port*: Port
+    bindAddr*: string
+    reusePort*: bool
+    futureErrorHandler*: proc (fut: Future[void]) {.closure, gcsafe.}
+
+  JesterError* = object of Exception
+
+proc parseUrlQuery*(query: string, result: var Table[string, string])
+    {.deprecated: "use stdlib".} =
+  var i = 0
+  i = query.skip("?")
+  while i < query.len()-1:
+    var key = ""
+    var val = ""
+    i += query.parseUntil(key, '=', i)
+    if query[i] != '=':
+      raise newException(ValueError, "Expected '=' at " & $i &
+                         " but got: " & $query[i])
+    inc(i) # Skip =
+    i += query.parseUntil(val, '&', i)
+    inc(i) # Skip &
+    result[decodeUrl(key)] = decodeUrl(val)
+
+template parseContentDisposition(): typed =
+  var hCount = 0
+  while hCount < hValue.len()-1:
+    var key = ""
+    hCount += hValue.parseUntil(key, {';', '='}, hCount)
+    if hValue[hCount] == '=':
+      var value = hvalue.captureBetween('"', start = hCount)
+      hCount += value.len+2
+      inc(hCount) # Skip ;
+      hCount += hValue.skipWhitespace(hCount)
+      if key == "name": name = value
+      newPart[0][key] = value
+    else:
+      inc(hCount)
+      hCount += hValue.skipWhitespace(hCount)
+
+proc parseMultiPart*(body: string, boundary: string): MultiData =
+  result = initOrderedTable[string, tuple[fields: StringTableRef, body: string]]()
+  var mboundary = "--" & boundary
+
+  var i = 0
+  var partsLeft = true
+  while partsLeft:
+    var firstBoundary = body.skip(mboundary, i)
+    if firstBoundary == 0:
+      raise newException(ValueError, "Expected boundary. Got: " & body.substr(i, i+25))
+    i += firstBoundary
+    i += body.skipWhitespace(i)
+
+    # Headers
+    var newPart: tuple[fields: StringTableRef, body: string] = ({:}.newStringTable, "")
+    var name = ""
+    while true:
+      if body[i] == '\c':
+        inc(i, 2) # Skip \c\L
+        break
+      var hName = ""
+      i += body.parseUntil(hName, ':', i)
+      if body[i] != ':':
+        raise newException(ValueError, "Expected : in headers.")
+      inc(i) # Skip :
+      i += body.skipWhitespace(i)
+      var hValue = ""
+      i += body.parseUntil(hValue, {'\c', '\L'}, i)
+      if toLowerAscii(hName) == "content-disposition":
+        parseContentDisposition()
+      newPart[0][hName] = hValue
+      i += body.skip("\c\L", i) # Skip *one* \c\L
+
+    # Parse body.
+    while true:
+      if body[i] == '\c' and body[i+1] == '\L' and
+         body.skip(mboundary, i+2) != 0:
+        if body.skip("--", i+2+mboundary.len) != 0:
+          partsLeft = false
+          break
+        break
+      else:
+        newPart[1].add(body[i])
+      inc(i)
+    i += body.skipWhitespace(i)
+
+    result.add(name, newPart)
+
+proc parseMPFD*(contentType: string, body: string): MultiData =
+  var boundaryEqIndex = contentType.find("boundary=")+9
+  var boundary = contentType.substr(boundaryEqIndex, contentType.len()-1)
+  return parseMultiPart(body, boundary)
+
+proc parseCookies*(s: string): Table[string, string] =
+  ## parses cookies into a string table.
+  ##
+  ## The proc is meant to parse the Cookie header set by a client, not the
+  ## "Set-Cookie" header set by servers.
+
+  result = initTable[string, string]()
+  var i = 0
+  while true:
+    i += skipWhile(s, {' ', '\t'}, i)
+    var keystart = i
+    i += skipUntil(s, {'='}, i)
+    var keyend = i-1
+    if i >= len(s): break
+    inc(i) # skip '='
+    var valstart = i
+    i += skipUntil(s, {';'}, i)
+    result[substr(s, keystart, keyend)] = substr(s, valstart, i-1)
+    if i >= len(s): break
+    inc(i) # skip ';'
+
+type
+  SameSite* = enum
+    None, Lax, Strict
+
+proc makeCookie*(key, value, expires: string, domain = "", path = "",
+                 secure = false, httpOnly = false,
+                 sameSite = Lax): string =
+  result = ""
+  result.add key & "=" & value
+  if domain != "": result.add("; Domain=" & domain)
+  if path != "": result.add("; Path=" & path)
+  if expires != "": result.add("; Expires=" & expires)
+  if secure: result.add("; Secure")
+  if httpOnly: result.add("; HttpOnly")
+  if sameSite != None:
+    result.add("; SameSite=" & $sameSite)
+
+when not declared(tables.getOrDefault):
+  template getOrDefault*(tab, key): untyped = tab[key]
+
+when not declared(normalizePath) and not declared(normalizedPath):
+  proc normalizePath*(path: var string) =
+    ## Normalize a path.
+    ##
+    ## Consecutive directory separators are collapsed, including an initial double slash.
+    ##
+    ## On relative paths, double dot (..) sequences are collapsed if possible.
+    ## On absolute paths they are always collapsed.
+    ##
+    ## Warning: URL-encoded and Unicode attempts at directory traversal are not detected.
+    ## Triple dot is not handled.
+    let isAbs = isAbsolute(path)
+    var stack: seq[string] = @[]
+    for p in split(path, {DirSep}):
+      case p
+      of "", ".":
+        continue
+      of "..":
+        if stack.len == 0:
+          if isAbs:
+            discard  # collapse all double dots on absoluta paths
+          else:
+            stack.add(p)
+        elif stack[^1] == "..":
+          stack.add(p)
+        else:
+          discard stack.pop()
+      else:
+        stack.add(p)
+
+    if isAbs:
+      path = DirSep & join(stack, $DirSep)
+    elif stack.len > 0:
+      path = join(stack, $DirSep)
+    else:
+      path = "."
+
+  proc normalizedPath*(path: string): string =
+    ## Returns a normalized path for the current OS. See `<#normalizePath>`_
+    result = path
+    normalizePath(result)
+
+when isMainModule:
+  var r = {:}.newStringTable
+  parseUrlQuery("FirstName=Mickey", r)
+  echo r
+