summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/asyncftpclient.nim19
-rw-r--r--lib/pure/ftpclient.nim19
2 files changed, 30 insertions, 8 deletions
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
index ff98d94c1..fe4577ed9 100644
--- a/lib/pure/asyncftpclient.nim
+++ b/lib/pure/asyncftpclient.nim
@@ -37,12 +37,24 @@ type
     proc (total, progress: BiggestInt, speed: float):
       Future[void] {.closure, gcsafe.}
 
-proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] =
-  result = ftp.csock.recvLine()
+const multiLineLimit = 10000
+
+proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
+  result = await ftp.csock.recvLine()
+  var count = 0
+  while result[3] == '-':
+    ## Multi-line reply.
+    let line = await ftp.csock.recvLine()
+    result.add("\n" & line)
+    count.inc()
+    if count >= multiLineLimit:
+      raise newException(ReplyError, "Reached maximum multi-line reply count.")
 
 proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
+  ##
+  ## **Note:** The server may return multiple lines of coded replies.
   await ftp.csock.send(m & "\c\L")
   return await ftp.expectReply()
 
@@ -82,9 +94,6 @@ proc connect*(ftp: AsyncFtpClient) {.async.} =
 
   # Handle 220 messages from the server
   assertReply(reply, "220")
-  while reply[3] == "-": # handle multiline 220 message
-    assertReply(reply, "220")
-    reply = await ftp.expectReply()
 
   if ftp.user != "":
     assertReply(await(ftp.send("USER " & ftp.user)), "230", "331")
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 2644fc010..778ba6857 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -107,6 +107,8 @@ type
   EInvalidReply: ReplyError, EFTP: FTPError
 ].}
 
+const multiLineLimit = 10000
+
 proc ftpClient*(address: string, port = Port(21),
                 user, pass = ""): FtpClient =
   ## Create a ``FtpClient`` object.
@@ -135,10 +137,24 @@ proc expectReply[T](ftp: FtpBase[T]): TaintedString =
       ftp.csock.readLine(result)
     else:
       discard ftp.csock.readLine(result)
+    var count = 0
+    while result[3] == '-':
+      ## Multi-line reply.
+      var line = TaintedString""
+      when T is Socket:
+        ftp.csock.readLine(line)
+      else:
+        discard ftp.csock.readLine(line)
+      result.add("\n" & line)
+      count.inc()
+      if count >= multiLineLimit:
+        raise newException(ReplyError, "Reached maximum multi-line reply count.")
 
 proc send*[T](ftp: FtpBase[T], m: string): TaintedString =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
+  ##
+  ## **Note:** The server may return multiple lines of coded replies.
   blockingOperation(ftp.csock):
     ftp.csock.send(m & "\c\L")
   return ftp.expectReply()
@@ -271,9 +287,6 @@ proc connect*[T](ftp: FtpBase[T]) =
 
   # Handle 220 messages from the server
   assertReply ftp.expectReply(), "220"
-  while reply[3] == "-": # handle multiline 220 message
-    assertReply ftp.expectReply(), "220"
-    reply = ftp.expectReply()
 
   if ftp.user != "":
     assertReply(ftp.send("USER " & ftp.user), "230", "331")