From 1df10adfe7eb20bc460eeb0e5a8e242970642c58 Mon Sep 17 00:00:00 2001 From: bptato Date: Tue, 12 Dec 2023 21:36:30 +0100 Subject: Move out ftp: protocol; fix some local CGI bugs --- src/loader/ftp.nim | 204 ----------------------------------------------------- 1 file changed, 204 deletions(-) delete mode 100644 src/loader/ftp.nim (limited to 'src/loader/ftp.nim') diff --git a/src/loader/ftp.nim b/src/loader/ftp.nim deleted file mode 100644 index bf69afff..00000000 --- a/src/loader/ftp.nim +++ /dev/null @@ -1,204 +0,0 @@ -import strutils - -import bindings/curl -import loader/connecterror -import loader/curlhandle -import loader/curlwrap -import loader/dirlist -import loader/headers -import loader/loaderhandle -import loader/request -import types/opt -import types/url -import utils/twtstr - -type FtpHandle = ref object of CurlHandle - buffer: string - dirmode: bool - base: string - path: string - -func newFtpHandle(curl: CURL, request: Request, handle: LoaderHandle, - dirmode: bool): FtpHandle = - return FtpHandle( - headers: newHeaders(), - curl: curl, - handle: handle, - request: request, - dirmode: dirmode - ) - -proc curlWriteHeader(p: cstring, size: csize_t, nitems: csize_t, - userdata: pointer): csize_t {.cdecl.} = - var line = newString(nitems) - if nitems > 0: - prepareMutation(line) - copyMem(addr line[0], p, nitems) - - let op = cast[FtpHandle](userdata) - - if not op.statusline: - if line.startsWith("150") or line.startsWith("125"): - op.statusline = true - if not op.handle.sendResult(int(CURLE_OK)): - return 0 - var status: clong - op.curl.getinfo(CURLINFO_RESPONSE_CODE, addr status) - if not op.handle.sendStatus(cast[int](status)): - return 0 - if op.dirmode: - op.headers.add("Content-Type", "text/html") - if not op.handle.sendHeaders(op.headers): - return 0 - if op.dirmode: - if not op.handle.sendData(""" - - - -""" & op.path & """ - - -

Index of """ & htmlEscape(op.path) & """

-
-"""):
-          return 0
-      return nitems
-    elif line.startsWith("530"): # login incorrect
-      op.statusline = true
-      if not op.handle.sendResult(int(CURLE_OK)):
-        return 0
-      var status: clong
-      op.curl.getinfo(CURLINFO_RESPONSE_CODE, addr status)
-      discard op.handle.sendStatus(401) # unauthorized (shim http)
-      op.headers.add("Content-Type", "text/html")
-      discard op.handle.sendHeaders(op.headers)
-      discard op.handle.sendData("""
-
-
-Unauthorized
-
-
-
-""" & htmlEscape(line))
-      return 0
-  return nitems
-
-# From the documentation: size is always 1.
-proc curlWriteBody(p: cstring, size: csize_t, nmemb: csize_t,
-    userdata: pointer): csize_t {.cdecl.} =
-  let op = cast[FtpHandle](userdata)
-
-  if nmemb > 0:
-    if op.dirmode:
-      let i = op.buffer.len
-      op.buffer.setLen(op.buffer.len + int(nmemb))
-      prepareMutation(op.buffer)
-      copyMem(addr op.buffer[i], p, nmemb)
-    else:
-      if not op.handle.sendData(p, int(nmemb)):
-        return 0
-  return nmemb
-
-proc finish(op: CurlHandle) =
-  let op = cast[FtpHandle](op)
-  var items: seq[DirlistItem]
-  for line in op.buffer.split('\n'):
-    if line.len == 0: continue
-    var i = 10 # permission
-    template skip_till_space =
-      while i < line.len and line[i] != ' ':
-        inc i
-    # link count
-    i = line.skipBlanks(i)
-    while i < line.len and line[i] in AsciiDigit:
-      inc i
-    # owner
-    i = line.skipBlanks(i)
-    skip_till_space
-    # group
-    i = line.skipBlanks(i)
-    while i < line.len and line[i] != ' ':
-      inc i
-    # size
-    i = line.skipBlanks(i)
-    var sizes = ""
-    while i < line.len and line[i] in AsciiDigit:
-      sizes &= line[i]
-      inc i
-    let nsize = parseInt64(sizes).get(-1)
-    # date
-    i = line.skipBlanks(i)
-    let datestarti = i
-    skip_till_space # m
-    i = line.skipBlanks(i)
-    skip_till_space # d
-    i = line.skipBlanks(i)
-    skip_till_space # y
-    let dates = line.substr(datestarti, i)
-    inc i
-    let name = line.substr(i)
-    if name == "." or name == "..": continue
-    case line[0]
-    of 'l': # link
-      let x = " -> "
-      let linki = name.find(x)
-      let linkfrom = name.substr(0, linki - 1)
-      let linkto = name.substr(linki + 4) # you?
-      items.add(DirlistItem(
-        t: ITEM_LINK,
-        name: linkfrom,
-        modified: dates,
-        linkto: linkto
-      ))
-    of 'd': # directory
-      items.add(DirlistItem(
-        t: ITEM_DIR,
-        name: name,
-        modified: dates
-      ))
-    else: # file
-      items.add(DirlistItem(
-        t: ITEM_FILE,
-        name: name,
-        modified: dates,
-        nsize: int(nsize)
-      ))
-  discard op.handle.sendData(makeDirlist(items))
-  discard op.handle.sendData("\n
\n\n\n") - -proc loadFtp*(handle: LoaderHandle, curlm: CURLM, - request: Request): CurlHandle = - let curl = curl_easy_init() - doAssert curl != nil - let surl = request.url.serialize() - let path = request.url.path.serialize_unicode() - # By default, cURL CWD's into relative paths, and an extra slash is - # necessary to specify absolute paths. - # This is incredibly confusing, and probably not what the user wanted. - # So we work around it by adding the extra slash ourselves. - let hackurl = newURL(request.url) - hackurl.setPathname('/' & request.url.pathname) - let csurl = hackurl.serialize() - curl.setopt(CURLOPT_URL, csurl) - let dirmode = path.len > 0 and path[^1] == '/' - let handleData = curl.newFtpHandle(request, handle, dirmode) - curl.setopt(CURLOPT_HEADERDATA, handleData) - curl.setopt(CURLOPT_HEADERFUNCTION, curlWriteHeader) - curl.setopt(CURLOPT_WRITEDATA, handleData) - curl.setopt(CURLOPT_WRITEFUNCTION, curlWriteBody) - curl.setopt(CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_SINGLECWD) - if dirmode: - handleData.finish = finish - handleData.base = surl - handleData.path = path - if request.proxy != nil: - let purl = request.proxy.serialize() - curl.setopt(CURLOPT_PROXY, purl) - if request.httpmethod != HTTP_GET: - discard handle.sendResult(int(ERROR_INVALID_METHOD)) - return nil - let res = curl_multi_add_handle(curlm, curl) - if res != CURLM_OK: - discard handle.sendResult(int(res)) - return nil - return handleData -- cgit 1.4.1-2-gfad0