summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-11-15 23:04:24 +0100
committerAraq <rumpf_a@web.de>2011-11-15 23:04:24 +0100
commitb05418a4310c5e9fb9074a66bccba13a95053616 (patch)
treee23067c5af8ba91c58c4f771b04ec9aa72c29669 /lib/pure
parent7819b84475ca6ba1cf3e9976c7140ea11775b81d (diff)
parent0698a3cafab6e639ba76910757afc35b2ce236d2 (diff)
downloadNim-b05418a4310c5e9fb9074a66bccba13a95053616.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/ftpclient.nim55
1 files changed, 53 insertions, 2 deletions
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 9f641cd3b..65c1bfefb 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -6,7 +6,7 @@
 #    distribution, for details about the copyright.
 #
 
-import sockets, strutils, parseutils, times
+import sockets, strutils, parseutils, times, os
 
 ## This module **partially** implements an FTP client as specified
 ## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_. 
@@ -54,6 +54,7 @@ type
     of JRetr, JStore:
       dsockClosed: bool
       file: TFile
+      filename: string
       total: biggestInt # In bytes.
       progress: biggestInt # In bytes.
       oneSecond: biggestInt # Bytes transferred in one second.
@@ -64,6 +65,7 @@ type
     EvTransferProgress, EvLines, EvRetr, EvStore
 
   TFTPEvent* = object ## Event
+    filename*: string
     case typ*: FTPEventType
     of EvLines:
       lines*: string ## Lines that have been transferred.
@@ -184,6 +186,47 @@ proc asyncLines(ftp: var TFTPClient, timeout: int): bool =
       assertReply ftp.expectReply(), "226"
       return true
 
+proc listDirs*(ftp: var TFTPClient, dir: string = "",
+               async = false): seq[string] =
+  ## Returns a list of filenames in the given directory. If ``dir`` is "",
+  ## the current directory is used. If ``async`` is true, this
+  ## function will return immediately and it will be your job to
+  ## call ``poll`` to progress this operation.
+
+  ftp.createJob(asyncLines, JRetrText)
+  ftp.pasv()
+
+  assertReply ftp.send("NLST " & dir), ["125", "150"]
+
+  if not async:
+    while not ftp.job.prc(ftp, 500): nil
+    result = splitLines(ftp.job.lines)
+    ftp.deleteJob()
+  else: return @[]
+
+proc fileExists*(ftp: var TFTPClient, file: string): bool =
+  ## Determines whether ``file`` exists.
+  ##
+  ## Warning: This function may block. Especially on directories with many
+  ## files, because a full list of file names must be retrieved.
+  var files = ftp.listDirs()
+  for f in items(files):
+    if f == file: return true
+
+proc createDir*(ftp: var TFTPClient, dir: string, recursive: bool = false) =
+  ## Creates a directory ``dir``. If ``recursive`` is true, the topmost
+  ## subdirectory of ``dir`` will be created first, following the secondmost...
+  ## etc. this allows you to give a full path as the ``dir`` without worrying
+  ## about subdirectories not existing.
+  if not recursive:
+    assertReply ftp.send("MKD " & dir), "257"
+  else:
+    var reply = TaintedString""
+    for p in split(dir, {os.dirSep, os.altSep}):
+      if p != "":
+        reply = ftp.send("MKD " & p)
+    assertReply reply, "257"
+
 proc list*(ftp: var TFTPClient, dir: string = "", async = false): string =
   ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
   ## working directory. If ``async`` is true, this function will return
@@ -233,6 +276,8 @@ proc asyncFile(ftp: var TFTPClient, timeout: int): bool =
 proc retrFile*(ftp: var TFTPClient, file, dest: string, async = false) =
   ## Downloads ``file`` and saves it to ``dest``. Usage of this function
   ## asynchronously is recommended to view the progress of the download.
+  ## The ``EvRetr`` event is given by ``poll`` when the download is finished,
+  ## and the ``filename`` field will be equal to ``file``.
   ftp.createJob(asyncFile, JRetr)
   ftp.job.file = open(dest, mode = fmWrite)
   ftp.pasv()
@@ -246,6 +291,7 @@ proc retrFile*(ftp: var TFTPClient, file, dest: string, async = false) =
     
   ftp.job.total = fileSize
   ftp.job.lastProgressReport = epochTime()
+  ftp.job.filename = file
 
   if not async:
     while not ftp.job.prc(ftp, 500): nil
@@ -281,10 +327,13 @@ proc store*(ftp: var TFTPClient, file, dest: string, async = false) =
   ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
   ## function asynchronously is recommended to view the progress of
   ## the download.
+  ## The ``EvStore`` event is given by ``poll`` when the upload is finished,
+  ## and the ``filename`` field will be equal to ``file``.
   ftp.createJob(asyncUpload, JStore)
   ftp.job.file = open(file)
   ftp.job.total = ftp.job.file.getFileSize()
   ftp.job.lastProgressReport = epochTime()
+  ftp.job.filename = file
   ftp.pasv()
   
   assertReply ftp.send("STOR " & dest), ["125", "150"]
@@ -304,10 +353,12 @@ proc poll*(ftp: var TFTPClient, r: var TFTPEvent, timeout = 500): bool =
         r.lines = ftp.job.lines
       of JRetr:
         r.typ = EvRetr
+        r.filename = ftp.job.filename
         if ftp.job.progress != ftp.job.total:
           raise newException(EFTP, "Didn't download full file.")
       of JStore:
         r.typ = EvStore
+        r.filename = ftp.job.filename
         if ftp.job.progress != ftp.job.total:
           raise newException(EFTP, "Didn't upload full file.")
       ftp.deleteJob()
@@ -321,6 +372,7 @@ proc poll*(ftp: var TFTPClient, r: var TFTPEvent, timeout = 500): bool =
         r.bytesTotal = ftp.job.total
         r.bytesFinished = ftp.job.progress
         r.speed = ftp.job.oneSecond
+        r.filename = ftp.job.filename
         ftp.job.oneSecond = 0
 
 proc close*(ftp: var TFTPClient) =
@@ -331,7 +383,6 @@ proc close*(ftp: var TFTPClient) =
   ftp.dsock.close()
 
 when isMainModule:
-  import os
   var ftp = FTPClient("ex.org", user = "user", pass = "p")
   ftp.connect()
   echo ftp.pwd()