# API reference

Table of Contents

- API reference
  - Modules and classes hierarchy
  - Users
  - Control connection
  - Data connection
  - Server (acceptor)
  - Filesystem
  - Extended classes
    - Extended handlers
    - Extended authorizers
    - Extended filesystems
    - Extended servers

pyftpdlib implements the server side of the FTP protocol as defined in RFC-959. This document is intended to serve as a simple API reference of most important classes and functions. After reading this you will probably want to read the tutorial including customization through the use of some example scripts.

## Modules and classes hierarchy

    pyftpdlib.authorizers
    pyftpdlib.authorizers.AuthenticationFailed
    pyftpdlib.authorizers.DummyAuthorizer
    pyftpdlib.authorizers.UnixAuthorizer
    pyftpdlib.authorizers.WindowsAuthorizer
    pyftpdlib.handlers
    pyftpdlib.handlers.FTPHandler
    pyftpdlib.handlers.TLS_FTPHandler
    pyftpdlib.handlers.DTPHandler
    pyftpdlib.handlers.TLS_DTPHandler
    pyftpdlib.handlers.ThrottledDTPHandler
    pyftpdlib.filesystems
    pyftpdlib.filesystems.FilesystemError
    pyftpdlib.filesystems.AbstractedFS
    pyftpdlib.filesystems.UnixFilesystem
    pyftpdlib.servers
    pyftpdlib.servers.FTPServer
    pyftpdlib.servers.ThreadedFTPServer
    pyftpdlib.servers.MultiprocessFTPServer
    pyftpdlib.ioloop
    pyftpdlib.ioloop.IOLoop
    pyftpdlib.ioloop.Connector
    pyftpdlib.ioloop.Acceptor
    pyftpdlib.ioloop.AsyncChat

## Users

class `pyftpdlib.authorizers.``DummyAuthorizer`

  Basic “dummy” authorizer class, suitable for subclassing to create your own custom authorizers. An “authorizer” is a class handling authentications and permissions of the FTP server. It is used inside `pyftpdlib.handlers.FTPHandler` class for verifying user’s password, getting users home directory, checking user permissions when a filesystem read/write event occurs and changing user before accessing the filesystem. DummyAuthorizer is the base authorizer, providing a platform independent interface for managing “virtual” FTP users. Typically the first thing you have to do is create an instance of this class and start adding ftp users:

      >>> from pyftpdlib.authorizers import DummyAuthorizer
      >>> authorizer = DummyAuthorizer()
      >>> authorizer.add_user('user', 'password', '/home/user', perm='elradfmwMT')
      >>> authorizer.add_anonymous('/home/nobody')

  `add_user`(username, password, homedir, perm="elr", msg_login="Login successful.", msg_quit="Goodbye.")

    Add a user to the virtual users table. AuthorizerError exception is raised on error conditions such as insufficient permissions or duplicate usernames. Optional perm argument is a set of letters referencing the user’s permissions. Every letter is used to indicate that the access rights the current FTP user has over the following specific actions are granted. The available permissions are the following listed below:

    Read permissions:

    - `"e"` = change directory (CWD, CDUP commands)
    - `"l"` = list files (LIST, NLST, STAT, MLSD, MLST, SIZE commands)
    - `"r"` = retrieve file from the server (RETR command)

    Write permissions:

    - `"a"` = append data to an existing file (APPE command)
    - `"d"` = delete file or directory (DELE, RMD commands)
    - `"f"` = rename file or directory (RNFR, RNTO commands)
    - `"m"` = create directory (MKD command)
    - `"w"` = store a file to the server (STOR, STOU commands)
    - `"M"` = change file mode / permission (SITE CHMOD command) New in 0.7.0
    - `"T"` = change file modification time (SITE MFMT command) New in 1.5.3

    Optional msg_login and msg_quit arguments can be specified to provide customized response strings when user log-in and quit. The perm argument of the `add_user()` method refers to user’s permissions. Every letter is used to indicate that the access rights the current FTP user has over the following specific actions are granted.

  `add_anonymous`(homedir, **kwargs)

    Add an anonymous user to the virtual users table. AuthorizerError exception is raised on error conditions such as insufficient permissions, missing home directory, or duplicate anonymous users. The keyword arguments in kwargs are the same expected by `add_user()` method: perm, msg_login and msg_quit. The optional perm keyword argument is a string defaulting to “elr” referencing “read-only” anonymous user’s permission. Using a “write” value results in a RuntimeWarning.

  `override_perm`(username, directory, perm, recursive=False)

    Override user permissions for a given directory.

  `validate_authentication`(username, password, handler)

    Raises `pyftpdlib.authorizers.AuthenticationFailed` if the supplied username and password doesn’t match the stored credentials.

    Changed in 1.0.0: new handler parameter.

    Changed in 1.0.0: an exception is now raised for signaling a failed authenticaiton as opposed to returning a bool.

  `impersonate_user`(username, password)

    Impersonate another user (noop). It is always called before accessing the filesystem. By default it does nothing. The subclass overriding this method is expected to provide a mechanism to change the current user.

  `terminate_impersonation`(username)

    Terminate impersonation (noop). It is always called after having accessed the filesystem. By default it does nothing. The subclass overriding this method is expected to provide a mechanism to switch back to the original user.

  `remove_user`(username)

    Remove a user from the virtual user table.

## Control connection

class `pyftpdlib.handlers.``FTPHandler`(conn, server)

  This class implements the FTP server Protocol Interpreter (see RFC-959), handling commands received from the client on the control channel by calling the command’s corresponding method (e.g. for received command “MKD pathname”, ftp_MKD() method is called with pathname as the argument). All relevant session information are stored in instance variables. conn is the underlying socket object instance of the newly established connection, server is the `pyftpdlib.servers.FTPServer` class instance. Basic usage simply requires creating an instance of FTPHandler class and specify which authorizer instance it will going to use:

      >>> from pyftpdlib.handlers import FTPHandler
      >>> handler = FTPHandler
      >>> handler.authorizer = authorizer

  All relevant session information is stored in class attributes reproduced below and can be modified before instantiating this class:

  `timeout`

    The timeout which is the maximum time a remote client may spend between FTP commands. If the timeout triggers, the remote client will be kicked off (defaults to `300` seconds).

    New in version 5.0

  `banner`

    String sent when client connects (default `"pyftpdlib %s ready." %__ver__`).

  `max_login_attempts`

    Maximum number of wrong authentications before disconnecting (default `3`).

  `permit_foreign_addresses`

    Whether enable FXP feature (default `False`).

  `permit_privileged_ports`

    Set to `True` if you want to permit active connections (PORT) over privileged ports (not recommended, default `False`).

  `masquerade_address`

    The “masqueraded” IP address to provide along PASV reply when pyftpdlib is running behind a NAT or other types of gateways. When configured pyftpdlib will hide its local address and instead use the public address of your NAT (default None).

  `masquerade_address_map`

    In case the server has multiple IP addresses which are all behind a NAT router, you may wish to specify individual masquerade_addresses for each of them. The map expects a dictionary containing private IP addresses as keys, and their corresponding public (masquerade) addresses as values (defaults to `{}`). New in version 0.6.0

  `passive_ports`

    What ports ftpd will use for its passive data transfers. Value expected is a list of integers (e.g. `range(60000, 65535)`). When configured pyftpdlib will no longer use kernel-assigned random ports (default `None`).

  `use_gmt_times`

    When `True` causes the server to report all ls and MDTM times in GMT and not local time (default `True`). New in version 0.6.0

  `tcp_no_delay`

    Controls the use of the TCP_NODELAY socket option which disables the Nagle algorithm resulting in significantly better performances (default `True` on all platforms where it is supported). New in version 0.6.0

  `use_sendfile`

    When `True` uses sendfile(2) system call to send a file resulting in faster uploads (from server to client). Works on UNIX only and requires pysendfile module to be installed separately.

    New in version 0.7.0

  `auth_failed_timeout`

    The amount of time the server waits before sending a response in case of failed authentication.

    New in version 1.5.0

  Follows a list of callback methods that can be overridden in a subclass. For blocking operations read the FAQ on how to run time consuming tasks.

  `on_connect`()

    Called when client connects.

    New in version 1.0.0

  `on_disconnect`()

    Called when connection is closed.

    New in version 1.0.0

  `on_login`(username)

    Called on user login.

    New in version 0.6.0

  `on_login_failed`(username, password)

    Called on failed user login.

    New in version 0.7.0

  `on_logout`(username)

    Called when user logs out due to QUIT or USER issued twice. This is not called if client just disconnects without issuing QUIT first.

    New in version 0.6.0

  `on_file_sent`(file)

    Called every time a file has been successfully sent. file is the absolute name of that file.

  `on_file_received`(file)

    Called every time a file has been successfully received. file is the absolute name of that file.

  `on_incomplete_file_sent`(file)

    Called every time a file has not been entirely sent (e.g. transfer aborted by client). file is the absolute name of that file.

    New in version 0.6.0

  `on_incomplete_file_received`(file)

    Called every time a file has not been entirely received (e.g. transfer aborted by client). file is the absolute name of that file. New in version 0.6.0

## Data connection

class `pyftpdlib.handlers.``DTPHandler`(sock_obj, cmd_channel)

  This class handles the server-data-transfer-process (server-DTP, see RFC-959) managing all transfer operations regarding the data channel. sock_obj is the underlying socket object instance of the newly established connection, cmd_channel is the `pyftpdlib.handlers.FTPHandler` class instance.

  Changed in version 1.0.0: added ioloop argument.

  `timeout`

    The timeout which roughly is the maximum time we permit data transfers to stall for with no progress. If the timeout triggers, the remote client will be kicked off (default `300` seconds).

  `ac_in_buffer_size`
  `ac_out_buffer_size`

    The buffer sizes to use when receiving and sending data (both defaulting to `65536` bytes). For LANs you may want this to be fairly large. Depending on available memory and number of connected clients setting them to a lower value can result in better performances.

class `pyftpdlib.handlers.``ThrottledDTPHandler`(sock_obj, cmd_channel)

  A `pyftpdlib.handlers.DTPHandler` subclass which wraps sending and receiving in a data counter and temporarily “sleeps” the channel so that you burst to no more than x Kb/sec average. Use it instead of `pyftpdlib.handlers.DTPHandler` to set transfer rates limits for both downloads and/or uploads (see the demo script showing the example usage).

  `read_limit`

    The maximum number of bytes to read (receive) in one second (defaults to `0` == no limit)

  `write_limit`

    The maximum number of bytes to write (send) in one second (defaults to `0` == no limit).

## Server (acceptor)

class `pyftpdlib.servers.``FTPServer`(address_or_socket, handler, ioloop=None, backlog=100)

  Creates a socket listening on address (an `(host, port)` tuple) or a pre- existing socket object, dispatching the requests to handler (typically `pyftpdlib.handlers.FTPHandler` class). Also, starts the asynchronous IO loop. backlog is the maximum number of queued connections passed to socket.listen(). If a connection request arrives when the queue is full the client may raise ECONNRESET.

  Changed in version 1.0.0: added ioloop argument.

  Changed in version 1.2.0: address can also be a pre-existing socket object.

  Changed in version 1.2.0: Added backlog argument.

  Changed in version 1.5.4: Support for the context manager protocol was added. Exiting the context manager is equivalent to calling :meth:`close_all`.

      >>> from pyftpdlib.servers import FTPServer
      >>> address = ('127.0.0.1', 21)
      >>> server = FTPServer(address, handler)
      >>> server.serve_forever()

  It can also be used as a context manager. Exiting the context manager is equivalent to calling `close_all()`.

      >>> with FTPServer(address, handler) as server:
      ...     server.serve_forever()

  `max_cons`

    Number of maximum simultaneous connections accepted (default `512`).

  `max_cons_per_ip`

    Number of maximum connections accepted for the same IP address (default `0` == no limit).

  `serve_forever`(timeout=None, blocking=True, handle_exit=True)

    Starts the asynchronous IO loop.

    Changed in version 1.0.0: no longer a classmethod; ‘use_poll’ and ‘count’ *parameters were removed. ‘blocking’ and ‘handle_exit’ parameters were *added

  `close`()

    Stop accepting connections without disconnecting currently connected clients.

  `close_all`()

    Tell `server_forever()` loop to stop and wait until it does. Also all connected clients will be closed.

    Changed in version 1.0.0: ‘map’ and ‘ignore_all’ parameters were removed.

## Filesystem

class `pyftpdlib.filesystems.``FilesystemError`

  Exception class which can be raised from within `pyftpdlib.filesystems.AbstractedFS` in order to send custom error messages to client. New in version 1.0.0

class `pyftpdlib.filesystems.``AbstractedFS`(root, cmd_channel)

  A class used to interact with the file system, providing a cross-platform interface compatible with both Windows and UNIX style filesystems where all paths use `"/"` separator. AbstractedFS distinguishes between “real” filesystem paths and “virtual” ftp paths emulating a UNIX chroot jail where the user can not escape its home directory (example: real “/home/user” path will be seen as “/” by the client). It also provides some utility methods and wraps around all os.* calls involving operations against the filesystem like creating files or removing directories. The contructor accepts two arguments: root which is the user “real” home directory (e.g. ‘/home/user’) and cmd_channel which is the `pyftpdlib.handlers.FTPHandler` class instance.

  Changed in version 0.6.0: root and cmd_channel arguments were added.

  `root`

    User’s home directory (“real”). Changed in version 0.7.0: support setattr()

  `cwd`

    User’s current working directory (“virtual”).

    Changed in version 0.7.0: support setattr()

  `ftpnorm`(ftppath)

    Normalize a “virtual” ftp pathname depending on the current working directory (e.g. having `"/foo"` as current working directory `"bar"` becomes `"/foo/bar"`).

  `ftp2fs`(ftppath)

    Translate a “virtual” ftp pathname into equivalent absolute “real” filesystem pathname (e.g. having `"/home/user"` as root directory `"foo"` becomes `"/home/user/foo"`).

  `fs2ftp`(fspath)

    Translate a “real” filesystem pathname into equivalent absolute “virtual” ftp pathname depending on the user’s root directory (e.g. having `"/home/user"` as root directory `"/home/user/foo"` becomes `"/foo"`.

  `validpath`(path)

    Check whether the path belongs to user’s home directory. Expected argument is a “real” filesystem path. If path is a symbolic link it is resolved to check its real destination. Pathnames escaping from user’s root directory are considered not valid (return `False`).

  `open`(filename, mode)

    Wrapper around open() builtin.

  `mkdir`(path)
  `chdir`(path)
  `rmdir`(path)
  `remove`(path)
  `rename`(src, dst)
  `chmod`(path, mode)
  `stat`(path)
  `lstat`(path)
  `readlink`(path)

    Wrappers around corresponding os module functions.

  `isfile`(path)
  `islink`(path)
  `isdir`(path)
  `getsize`(path)
  `getmtime`(path)
  `realpath`(path)
  `lexists`(path)

    Wrappers around corresponding os.path module functions.

  `mkstemp`(suffix='', prefix='', dir=None, mode='wb')

    Wrapper around tempfile.mkstemp.

  `listdir`(path)

    Wrapper around os.listdir. It is expected to return a list of unicode strings or a generator yielding unicode strings.

    Changed in version 1.6.0: can also return a generator.

## Extended classes

> We are about to introduces are extensions (subclasses) of the ones explained so far. They usually require third-party modules to be installed separately or are specific for a given Python version or operating system.

### Extended handlers

class `pyftpdlib.handlers.``TLS_FTPHandler`(conn, server)

  A `pyftpdlib.handlers.FTPHandler` subclass implementing FTPS (FTP over SSL/TLS) as described in RFC-4217 implementing AUTH, PBSZ and PROT commands. PyOpenSSL module is required to be installed. Example below shows how to setup an FTPS server. Configurable attributes:

  `certfile`

    The path to a file which contains a certificate to be used to identify the local side of the connection. This must always be specified, unless context is provided instead.

  `keyfile`

    The path of the file containing the private RSA key; can be omittetted if certfile already contains the private key (defaults: `None`).

  `ssl_protocol`

    The desired SSL protocol version to use. This defaults to SSL.SSLv23_METHOD which will negotiate the highest protocol that both the server and your installation of OpenSSL support.

  `ssl_options`

    specific OpenSSL options. These default to: SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_NO_COMPRESSION disabling SSLv2 and SSLv3 versions and SSL compression algorithm which are considered insecure. Can be set to None in order to improve compatibilty with older (insecure) FTP clients.

    New in version 1.6.0.

  `ssl_context`

    A SSL.Context instance which was previously configured. If specified `ssl_protocol` and `ssl_options` parameters will be ignored.

  `tls_control_required`

    When True requires SSL/TLS to be established on the control channel, before logging in. This means the user will have to issue AUTH before USER/PASS (default `False`).

  `tls_data_required`

    When True requires SSL/TLS to be established on the data channel. This means the user will have to issue PROT before PASV or PORT (default `False`).

### Extended authorizers

class `pyftpdlib.authorizers.``UnixAuthorizer`(global_perm="elradfmwMT", allowed_users=None, rejected_users=None, require_valid_shell=True, anonymous_user=None, msg_login="Login successful.", msg_quit="Goodbye.")

  Authorizer which interacts with the UNIX password database. Users are no longer supposed to be explicitly added as when using `pyftpdlib.authorizers.DummyAuthorizer`. All FTP users are the same defined on the UNIX system so if you access on your system by using `"john"` as username and `"12345"` as password those same credentials can be used for accessing the FTP server as well. The user home directories will be automatically determined when user logins. Every time a filesystem operation occurs (e.g. a file is created or deleted) the id of the process is temporarily changed to the effective user id and whether the operation will succeed depends on user and file permissions. This is why full read and write permissions are granted by default in the class constructors.

  global_perm is a series of letters referencing the users permissions; defaults to “elradfmwMT” which means full read and write access for everybody (except anonymous). allowed_users and rejected_users options expect a list of users which are accepted or rejected for authenticating against the FTP server; defaults both to `[]` (no restrictions). require_valid_shell denies access for those users which do not have a valid shell binary listed in /etc/shells. If /etc/shells cannot be found this is a no-op. anonymous user is not subject to this option, and is free to not have a valid shell defined. Defaults to `True` (a valid shell is required for login). anonymous_user can be specified if you intend to provide anonymous access. The value expected is a string representing the system user to use for managing anonymous sessions; defaults to `None` (anonymous access disabled). Note that in order to use this class super user privileges are required.

  New in version 0.6.0

  `override_user`(username=None, password=None, homedir=None, perm=None, anonymous_user=None, msg_login=None, msg_quit=None)

    Overrides one or more options specified in the class constructor for a specific user. Example:

        >>> from pyftpdlib.authorizers import UnixAuthorizer
        >>> auth = UnixAuthorizer(rejected_users=["root"])
        >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
        >>> auth = UnixAuthorizer(require_valid_shell=False)
        >>> auth.override_user("matt", password="foo", perm="elr")

class `pyftpdlib.authorizers.``WindowsAuthorizer`(global_perm="elradfmwMT", allowed_users=None, rejected_users=None, anonymous_user=None, anonymous_password="", msg_login="Login successful.", msg_quit="Goodbye.")

  Same as `pyftpdlib.authorizers.UnixAuthorizer` except for anonymous_password argument which must be specified when defining the anonymous_user. Also requires_valid_shell option is not available. In order to use this class pywin32 extension must be installed.

  New in version 0.6.0

### Extended filesystems

class `pyftpdlib.filesystems.``UnixFilesystem`(root, cmd_channel)

  Represents the real UNIX filesystem. Differently from `pyftpdlib.filesystems.AbstractedFS` the client will login into /home/<username> and will be able to escape its home directory and navigate the real filesystem. Use it in conjuction with `pyftpdlib.authorizers.UnixAuthorizer` to implement a “real” UNIX FTP server (see demo/unix_ftpd.py).

  New in version 0.6.0

### Extended servers

class `pyftpdlib.servers.``ThreadedFTPServer`(address_or_socket, handler, ioloop=None, backlog=5)

  A modified version of base `pyftpdlib.servers.FTPServer` class which spawns a thread every time a new connection is established. Differently from base FTPServer class, the handler will be free to block without hanging the whole IO loop.

  New in version 1.0.0

  Changed in 1.2.0: added ioloop parameter; address can also be a pre-existing *socket.

class `pyftpdlib.servers.``MultiprocessFTPServer`(address_or_socket, handler, ioloop=None, backlog=5)

  A modified version of base `pyftpdlib.servers.FTPServer` class which spawns a process every time a new connection is established. Differently from base FTPServer class, the handler will be free to block without hanging the whole IO loop.

  New in version 1.0.0

  Changed in 1.2.0: added ioloop parameter; address can also be a pre-existing socket.

  Availability: POSIX + Python >= 2.6