# Module ftpclient

This module partially implements an FTP client as specified by RFC 959.

This module provides both a synchronous and asynchronous implementation. The asynchronous implementation requires you to use the `AsyncFTPClient` function. You are then required to register the `PAsyncFTPClient` with a asyncio dispatcher using the `register` function. Take a look at the asyncio module documentation for more information.

Note: The asynchronous implementation is only asynchronous for long file transfers, calls to functions which use the command socket will block.

Here is some example usage of this module:

    var ftp = FTPClient("example.org", user = "user", pass = "pass")
    ftp.connect()
    ftp.retrFile("file.ext", "file.ext")

Warning: The API of this module is unstable, and therefore is subject to change.

# Imports

sockets, strutils, parseutils, times, os, asyncio

# Types

    TFTPClient = object of TObject
      case isAsync: bool
      of false:
          csock: TSocket
          dsock: TSocket

      else:
          dummyA, dummyB: pointer
          asyncCSock: PAsyncSocket
          asyncDSock: PAsyncSocket
          handleEvent*: proc (ftp: PAsyncFTPClient; ev: TFTPEvent) {.closure.}
          disp: PDispatcher
          asyncDSockID: PDelegate

      user, pass: string
      address: string
      port: TPort
      jobInProgress: bool
      job: ref TFTPJob
      dsockConnected: bool

    PFTPClient = ref TFTPClient

    FTPJobType = enum
      JRetrText, JRetr, JStore

    PAsyncFTPClient = ref TAsyncFTPClient

  Async alternative to TFTPClient.

    TAsyncFTPClient = object of TFTPClient

    FTPEventType = enum
      EvTransferProgress, EvLines, EvRetr, EvStore

    TFTPEvent = object
      filename*: string
      case typ*: FTPEventType
      of EvLines:
          lines*: string          ## Lines that have been transferred.

      of EvRetr, EvStore:         ## Retr/Store operation finished.
          nil

      of EvTransferProgress:
          bytesTotal*: BiggestInt ## Bytes total.
          bytesFinished*: BiggestInt ## Bytes transferred.
          speed*: BiggestInt      ## Speed in bytes/s
          currentJob*: FTPJobType ## The current job being performed.

  Event

    EInvalidReply = object of ESynch

    EFTP = object of ESynch

# Procs

    proc FTPClient(address: string; port = TPort(21); user, pass = ""): PFTPClient {.
        raises: [], tags: [].}

  Create a `PFTPClient` object.

    proc send(ftp: PFTPClient; m: string): TaintedString {.raises: [EOS, ETimeout],
        tags: [FWriteIO, FReadIO, FTime].}

  Send a message to the server, and wait for a primary reply. `\c\L` is added for you.

    proc connect(ftp: PFTPClient) {.raises: [EOS, EInvalidReply, EInvalidValue,
        ETimeout], tags: [FReadIO, FTime, FWriteIO].}

  Connect to the FTP server specified by `ftp`.

    proc pwd(ftp: PFTPClient): string {.raises: [EOS, ETimeout, EInvalidReply,
        EInvalidValue], tags: [FWriteIO, FReadIO, FTime].}

  Returns the current working directory.

    proc cd(ftp: PFTPClient; dir: string) {.raises: [EInvalidReply, EInvalidValue,
        EOS, ETimeout], tags: [FWriteIO, FReadIO, FTime].}

  Changes the current directory on the remote FTP server to `dir`.

    proc cdup(ftp: PFTPClient) {.raises: [EInvalidReply, EInvalidValue, EOS,
                                          ETimeout],
                                 tags: [FWriteIO, FReadIO, FTime].}

  Changes the current directory to the parent of the current directory.

    proc listDirs(ftp: PFTPClient; dir: string = ""; async = false): seq[string] {.raises: [
        EFTP, EOS, ETimeout, EInvalidReply, EInvalidValue, E_Base, EOverflow],
        tags: [FReadIO, FTime, TEffect, FWriteIO].}

  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 use asyncio's `poll` to progress this operation.

    proc fileExists(ftp: PFTPClient; file: string): bool {.deprecated, raises: [
        EFTP, EOS, ETimeout, EInvalidReply, EInvalidValue, E_Base, EOverflow],
        tags: [FReadIO, FTime, TEffect, FWriteIO].}

  Deprecated since version 0.9.0: Please use `existsFile`.

  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.

    proc existsFile(ftp: PFTPClient; file: string): bool {.raises: [EFTP, EOS,
        ETimeout, EInvalidReply, EInvalidValue, E_Base, EOverflow],
        tags: [FReadIO, FTime, TEffect, FWriteIO].}

  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.

    proc createDir(ftp: PFTPClient; dir: string; recursive: bool = false) {.
        raises: [EInvalidReply, EInvalidValue, EOS, ETimeout],
        tags: [FWriteIO, FReadIO, FTime].}

  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.

    proc chmod(ftp: PFTPClient; path: string; permissions: set[TFilePermission]) {.
        raises: [EInvalidReply, EInvalidValue, EOS, ETimeout],
        tags: [FWriteIO, FReadIO, FTime].}

  Changes permission of `path` to `permissions`.

    proc list(ftp: PFTPClient; dir: string = ""; async = false): string {.raises: [
        EFTP, EOS, ETimeout, EInvalidReply, EInvalidValue, E_Base, EOverflow],
        tags: [FReadIO, FTime, TEffect, FWriteIO].}

  Lists all files in `dir`. If `dir` is `""`, uses the current working directory. If `async` is true, this function will return immediately and it will be your job to call asyncio's `poll` to progress this operation.

    proc retrText(ftp: PFTPClient; file: string; async = false): string {.raises: [
        EFTP, EOS, ETimeout, EInvalidReply, EInvalidValue, E_Base, EOverflow],
        tags: [FReadIO, FTime, TEffect, FWriteIO].}

  Retrieves `file`. File must be ASCII text. If `async` is true, this function will return immediately and it will be your job to call asyncio's `poll` to progress this operation.

    proc retrFile(ftp: PFTPClient; file, dest: string; async = false) {.raises: [
        EFTP, EOS, ETimeout, EIO, EInvalidReply, EInvalidValue, E_Base, EOverflow,
        EInvalidReply, EInvalidReply], tags: [FReadIO, FTime, FWriteIO, TEffect].}

  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 passed to the specified `handleEvent` function when the download is finished, and the `filename` field will be equal to `file`.

    proc store(ftp: PFTPClient; file, dest: string; async = false) {.raises: [EFTP,
        EOS, EInvalidReply, EInvalidValue, ETimeout, E_Base, EIO, EOverflow],
        tags: [FWriteIO, FReadIO, FTime, TEffect].}

  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 passed to the specified `handleEvent` function when the upload is finished, and the `filename` field will be equal to `file`.

    proc close(ftp: PFTPClient) {.raises: [EInvalidReply, EInvalidValue, EOS,
                                           ETimeout],
                                  tags: [FWriteIO, FReadIO, FTime].}

  Terminates the connection to the server.

    proc AsyncFTPClient(address: string; port = TPort(21); user, pass = "";
        handleEvent: proc (ftp: PAsyncFTPClient; ev: TFTPEvent) {.closure.} = (proc (
        ftp: PAsyncFTPClient; ev: TFTPEvent) =
      nil)): PAsyncFTPClient {.raises: [EOS, EInvalidReply, EInvalidValue, ETimeout,
                                        EFTP, E_Base],
                               tags: [FReadIO, FTime, TEffect].}

  Create a `PAsyncFTPClient` object.

  Use this if you want to use asyncio's dispatcher.

    proc register(d: PDispatcher; ftp: PAsyncFTPClient): PDelegate {.discardable,
        raises: [], tags: [].}

  Registers `ftp` with dispatcher `d`.

Generated: 2013-05-21 09:55:23 UTC