summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-07-02 16:18:35 +0200
committerAraq <rumpf_a@web.de>2015-07-02 16:18:35 +0200
commit9b01f1bedb464e860f8c0f1ffa2df8c17bc26fb7 (patch)
tree890677483d7e6cb9714a1d5629414df7cbcded12
parentcabbcd411d93ab1787414715b68b5239a9cee2ae (diff)
parentcf63f90d0ff8586dfba218d2dd80bdb84bf69627 (diff)
downloadNim-9b01f1bedb464e860f8c0f1ffa2df8c17bc26fb7.tar.gz
Merge branch 'devel' of https://github.com/Araq/Nim into devel
-rw-r--r--lib/pure/asyncftpclient.nim18
-rw-r--r--lib/pure/ftpclient.nim24
-rw-r--r--lib/pure/httpclient.nim18
-rw-r--r--readme.md2
4 files changed, 58 insertions, 4 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 != "":
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 6a2913713..2ca2098b3 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -821,6 +821,24 @@ proc get*(client: AsyncHttpClient, url: string): Future[Response] {.async.} =
       result = await client.request(redirectTo, httpGET)
       lastUrl = redirectTo
 
+proc post*(client: AsyncHttpClient, url: string, body = "", multipart: MultipartData = nil): Future[Response] {.async.} =
+  ## Connects to the hostname specified by the URL and performs a POST request.
+  ##
+  ## This procedure will follow redirects up to a maximum number of redirects
+  ## specified in ``newAsyncHttpClient``.
+  let (mpHeader, mpBody) = format(multipart)
+
+  template withNewLine(x): expr =
+    if x.len > 0 and not x.endsWith("\c\L"):
+      x & "\c\L"
+    else:
+      x
+  var xb = mpBody.withNewLine() & body
+  client.headers["Content-Type"] = mpHeader.split(": ")[1]
+  client.headers["Content-Length"] = $len(xb)
+
+  result = await client.request(url, httpPOST, xb)
+      
 when not defined(testing) and isMainModule:
   when true:
     # Async
diff --git a/readme.md b/readme.md
index 740296f4f..277ceb8f3 100644
--- a/readme.md
+++ b/readme.md
@@ -26,7 +26,7 @@ To build from source you will need:
 If you are on a fairly modern *nix system, the following steps should work:
 
 ```
-$ git clone git://github.com/Araq/Nim.git
+$ git clone git://github.com/nim-lang/Nim.git
 $ cd Nim
 $ git clone --depth 1 git://github.com/nim-lang/csources
 $ cd csources && sh build.sh