diff options
-rw-r--r-- | lib/pure/asyncftpclient.nim | 18 | ||||
-rw-r--r-- | lib/pure/ftpclient.nim | 24 |
2 files changed, 39 insertions, 3 deletions
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim index daf69d59f..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() @@ -79,6 +91,8 @@ proc connect*(ftp: AsyncFtpClient) {.async.} = # 120 Service ready in nnn minutes. # We wait until we receive 220. reply = await ftp.expectReply() + + # Handle 220 messages from the server assertReply(reply, "220") if ftp.user != "": diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index dd141eb01..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() @@ -263,7 +279,13 @@ proc connect*[T](ftp: FtpBase[T]) = else: {.fatal: "Incorrect socket instantiation".} - # TODO: Handle 120? or let user handle it. + var reply = ftp.expectReply() + if reply.startsWith("120"): + # 120 Service ready in nnn minutes. + # We wait until we receive 220. + reply = ftp.expectReply() + + # Handle 220 messages from the server assertReply ftp.expectReply(), "220" if ftp.user != "": |