1=============
2API reference
3=============
4
5.. contents:: Table of Contents
6
7pyftpdlib implements the server side of the FTP protocol as defined in
8`RFC-959 <http://www.faqs.org/rfcs/rfc959.html>`_. This document is intended to
9serve as a simple API reference of most important classes and functions.
10After reading this you will probably want to read the
11`tutorial <tutorial.html>`_ including customization through the use of some
12example scripts.
13
14Modules and classes hierarchy
15=============================
16
17::
18
19  pyftpdlib.authorizers
20  pyftpdlib.authorizers.AuthenticationFailed
21  pyftpdlib.authorizers.DummyAuthorizer
22  pyftpdlib.authorizers.UnixAuthorizer
23  pyftpdlib.authorizers.WindowsAuthorizer
24  pyftpdlib.handlers
25  pyftpdlib.handlers.FTPHandler
26  pyftpdlib.handlers.TLS_FTPHandler
27  pyftpdlib.handlers.DTPHandler
28  pyftpdlib.handlers.TLS_DTPHandler
29  pyftpdlib.handlers.ThrottledDTPHandler
30  pyftpdlib.filesystems
31  pyftpdlib.filesystems.FilesystemError
32  pyftpdlib.filesystems.AbstractedFS
33  pyftpdlib.filesystems.UnixFilesystem
34  pyftpdlib.servers
35  pyftpdlib.servers.FTPServer
36  pyftpdlib.servers.ThreadedFTPServer
37  pyftpdlib.servers.MultiprocessFTPServer
38  pyftpdlib.ioloop
39  pyftpdlib.ioloop.IOLoop
40  pyftpdlib.ioloop.Connector
41  pyftpdlib.ioloop.Acceptor
42  pyftpdlib.ioloop.AsyncChat
43
44Users
45=====
46
47.. class:: pyftpdlib.authorizers.DummyAuthorizer()
48
49  Basic "dummy" authorizer class, suitable for subclassing to create your own
50  custom authorizers. An "authorizer" is a class handling authentications and
51  permissions of the FTP server. It is used inside
52  :class:`pyftpdlib.handlers.FTPHandler` class for verifying user's password,
53  getting users home directory, checking user permissions when a filesystem
54  read/write event occurs and changing user before accessing the filesystem.
55  DummyAuthorizer is the base authorizer, providing a platform independent
56  interface for managing "virtual" FTP users. Typically the first thing you
57  have to do is create an instance of this class and start adding ftp users:
58
59  >>> from pyftpdlib.authorizers import DummyAuthorizer
60  >>> authorizer = DummyAuthorizer()
61  >>> authorizer.add_user('user', 'password', '/home/user', perm='elradfmwMT')
62  >>> authorizer.add_anonymous('/home/nobody')
63
64  .. method:: add_user(username, password, homedir, perm="elr", msg_login="Login successful.", msg_quit="Goodbye.")
65
66    Add a user to the virtual users table. AuthorizerError exception is raised
67    on error conditions such as insufficient permissions or duplicate usernames.
68    Optional *perm* argument is a set of letters referencing the user's
69    permissions. Every letter is used to indicate that the access rights the
70    current FTP user has over the following specific actions are granted. The
71    available permissions are the following listed below:
72
73    Read permissions:
74
75    - ``"e"`` = change directory (CWD, CDUP commands)
76    - ``"l"`` = list files (LIST, NLST, STAT, MLSD, MLST, SIZE commands)
77    - ``"r"`` = retrieve file from the server (RETR command)
78
79    Write permissions:
80
81    - ``"a"`` = append data to an existing file (APPE command)
82    - ``"d"`` = delete file or directory (DELE, RMD commands)
83    - ``"f"`` = rename file or directory (RNFR, RNTO commands)
84    - ``"m"`` = create directory (MKD command)
85    - ``"w"`` = store a file to the server (STOR, STOU commands)
86    - ``"M"`` = change file mode / permission (SITE CHMOD command) *New in 0.7.0*
87    - ``"T"`` = change file modification time (SITE MFMT command) *New in 1.5.3*
88
89    Optional *msg_login* and *msg_quit* arguments can be specified to provide
90    customized response strings when user log-in and quit. The *perm* argument
91    of the :meth:`add_user()` method refers to user's permissions. Every letter
92    is used to indicate that the access rights the current FTP user has over
93    the following specific actions are granted.
94
95  .. method:: add_anonymous(homedir, **kwargs)
96
97    Add an anonymous user to the virtual users table. AuthorizerError exception
98    is raised on error conditions such as insufficient permissions, missing
99    home directory, or duplicate anonymous users. The keyword arguments in
100    kwargs are the same expected by :meth:`add_user()` method: *perm*,
101    *msg_login* and *msg_quit*. The optional perm keyword argument is a string
102    defaulting to "elr" referencing "read-only" anonymous user's permission.
103    Using a "write" value results in a RuntimeWarning.
104
105  .. method:: override_perm(username, directory, perm, recursive=False)
106
107    Override user permissions for a given directory.
108
109  .. method:: validate_authentication(username, password, handler)
110
111    Raises :class:`pyftpdlib.authorizers.AuthenticationFailed` if the supplied
112    username and password doesn't match the stored credentials.
113
114    *Changed in 1.0.0: new handler parameter.*
115
116    *Changed in 1.0.0: an exception is now raised for signaling a failed authenticaiton as opposed to returning a bool.*
117
118  .. method:: impersonate_user(username, password)
119
120    Impersonate another user (noop). It is always called before accessing the
121    filesystem. By default it does nothing. The subclass overriding this method
122    is expected to provide a mechanism to change the current user.
123
124  .. method:: terminate_impersonation(username)
125
126    Terminate impersonation (noop). It is always called after having accessed
127    the filesystem. By default it does nothing. The subclass overriding this
128    method is expected to provide a mechanism to switch back to the original
129    user.
130
131  .. method:: remove_user(username)
132
133    Remove a user from the virtual user table.
134
135Control connection
136==================
137
138.. class:: pyftpdlib.handlers.FTPHandler(conn, server)
139
140  This class implements the FTP server Protocol Interpreter (see
141  `RFC-959 <http://www.faqs.org/rfcs/rfc959.html>`_), handling commands received
142  from the client on the control channel by calling the command's corresponding
143  method (e.g. for received command "MKD pathname", ftp_MKD() method is called
144  with pathname as the argument). All relevant session information are stored
145  in instance variables. conn is the underlying socket object instance of the
146  newly established connection, server is the
147  :class:`pyftpdlib.servers.FTPServer` class instance. Basic usage simply
148  requires creating an instance of FTPHandler class and specify which
149  authorizer instance it will going to use:
150
151  >>> from pyftpdlib.handlers import FTPHandler
152  >>> handler = FTPHandler
153  >>> handler.authorizer = authorizer
154
155  All relevant session information is stored in class attributes reproduced
156  below and can be modified before instantiating this class:
157
158  .. data:: timeout
159
160    The timeout which is the maximum time a remote client may spend between FTP
161    commands. If the timeout triggers, the remote client will be kicked off
162    (defaults to ``300`` seconds).
163
164    *New in version 5.0*
165
166  .. data:: banner
167
168    String sent when client connects (default
169    ``"pyftpdlib %s ready." %__ver__``).
170
171  .. data:: max_login_attempts
172
173    Maximum number of wrong authentications before disconnecting (default
174    ``3``).
175
176  .. data:: permit_foreign_addresses
177
178    Whether enable FXP feature (default ``False``).
179
180  .. data:: permit_privileged_ports
181
182    Set to ``True`` if you want to permit active connections (PORT) over
183    privileged ports (not recommended, default ``False``).
184
185  .. data:: masquerade_address
186
187    The "masqueraded" IP address to provide along PASV reply when pyftpdlib is
188    running behind a NAT or other types of gateways. When configured pyftpdlib
189    will hide its local address and instead use the public address of your NAT
190    (default None).
191
192  .. data:: masquerade_address_map
193
194    In case the server has multiple IP addresses which are all behind a NAT
195    router, you may wish to specify individual masquerade_addresses for each of
196    them. The map expects a dictionary containing private IP addresses as keys,
197    and their corresponding public (masquerade) addresses as values (defaults
198    to ``{}``). *New in version 0.6.0*
199
200  .. data:: passive_ports
201
202    What ports ftpd will use for its passive data transfers. Value expected is
203    a list of integers (e.g. ``range(60000, 65535)``). When configured
204    pyftpdlib will no longer use kernel-assigned random ports (default
205    ``None``).
206
207  .. data:: use_gmt_times
208
209    When ``True`` causes the server to report all ls and MDTM times in GMT and
210    not local time (default ``True``). *New in version 0.6.0*
211
212  .. data:: tcp_no_delay
213
214    Controls the use of the TCP_NODELAY socket option which disables the Nagle
215    algorithm resulting in significantly better performances (default ``True``
216    on all platforms where it is supported). *New in version 0.6.0*
217
218  .. data:: use_sendfile
219
220    When ``True`` uses sendfile(2) system call to send a file resulting in
221    faster uploads (from server to client). Works on UNIX only and requires
222    `pysendfile <https://github.com/giampaolo/pysendfile>`__ module to be
223    installed separately.
224
225    *New in version 0.7.0*
226
227  .. data:: auth_failed_timeout
228
229    The amount of time the server waits before sending a response in case of
230    failed authentication.
231
232    *New in version 1.5.0*
233
234  Follows a list of callback methods that can be overridden in a subclass. For
235  blocking operations read the FAQ on how to run time consuming tasks.
236
237  .. method:: on_connect()
238
239    Called when client connects.
240
241    *New in version 1.0.0*
242
243  .. method:: on_disconnect()
244
245    Called when connection is closed.
246
247    *New in version 1.0.0*
248
249  .. method:: on_login(username)
250
251    Called on user login.
252
253    *New in version 0.6.0*
254
255  .. method:: on_login_failed(username, password)
256
257    Called on failed user login.
258
259    *New in version 0.7.0*
260
261  .. method:: on_logout(username)
262
263    Called when user logs out due to QUIT or USER issued twice. This is not
264    called if client just disconnects without issuing QUIT first.
265
266    *New in version 0.6.0*
267
268  .. method:: on_file_sent(file)
269
270    Called every time a file has been successfully sent. *file* is the
271    absolute name of that file.
272
273  .. method:: on_file_received(file)
274
275    Called every time a file has been successfully received. *file* is the
276    absolute name of that file.
277
278  .. method:: on_incomplete_file_sent(file)
279
280    Called every time a file has not been entirely sent (e.g. transfer aborted
281    by client). *file* is the absolute name of that file.
282
283    *New in version 0.6.0*
284
285  .. method:: on_incomplete_file_received(file)
286
287    Called every time a file has not been entirely received (e.g. transfer
288    aborted by client). *file* is the absolute name of that file. *New in
289    version 0.6.0*
290
291Data connection
292===============
293
294.. class:: pyftpdlib.handlers.DTPHandler(sock_obj, cmd_channel)
295
296  This class handles the server-data-transfer-process (server-DTP, see `RFC-959
297  <http://www.faqs.org/rfcs/rfc959.html>`_) managing all transfer operations
298  regarding the data channel. *sock_obj* is the underlying socket object
299  instance of the newly established connection, cmd_channel is the
300  :class:`pyftpdlib.handlers.FTPHandler` class instance.
301
302  *Changed in version 1.0.0: added ioloop argument.*
303
304  .. data:: timeout
305
306    The timeout which roughly is the maximum time we permit data transfers to
307    stall for with no progress. If the timeout triggers, the remote client will
308    be kicked off (default ``300`` seconds).
309
310  .. data:: ac_in_buffer_size
311  .. data:: ac_out_buffer_size
312
313    The buffer sizes to use when receiving and sending data (both defaulting to
314    ``65536`` bytes). For LANs you may want this to be fairly large. Depending
315    on available memory and number of connected clients setting them to a lower
316    value can result in better performances.
317
318
319.. class:: pyftpdlib.handlers.ThrottledDTPHandler(sock_obj, cmd_channel)
320
321  A :class:`pyftpdlib.handlers.DTPHandler` subclass which wraps sending and
322  receiving in a data counter and temporarily "sleeps" the channel so that you
323  burst to no more than x Kb/sec average. Use it instead of
324  :class:`pyftpdlib.handlers.DTPHandler` to set transfer rates limits for both
325  downloads and/or uploads (see the
326  `demo script <https://github.com/giampaolo/pyftpdlib/blob/master/demo/throttled_ftpd.py>`__
327  showing the example usage).
328
329  .. data:: read_limit
330
331    The maximum number of bytes to read (receive) in one second (defaults to
332    ``0`` == no limit)
333
334  .. data:: write_limit
335
336    The maximum number of bytes to write (send) in one second (defaults to
337    ``0`` == no limit).
338
339Server (acceptor)
340=================
341
342.. class:: pyftpdlib.servers.FTPServer(address_or_socket, handler, ioloop=None, backlog=100)
343
344  Creates a socket listening on *address* (an ``(host, port)`` tuple) or a
345  pre- existing socket object, dispatching the requests to *handler* (typically
346  :class:`pyftpdlib.handlers.FTPHandler` class). Also, starts the asynchronous
347  IO loop. *backlog* is the maximum number of queued connections passed to
348  `socket.listen() <http://docs.python.org/library/socket.html#socket.socket.listen>`_.
349  If a connection request arrives when the queue is full the client may raise
350  ECONNRESET.
351
352  *Changed in version 1.0.0: added ioloop argument.*
353
354  *Changed in version 1.2.0: address can also be a pre-existing socket object.*
355
356  *Changed in version 1.2.0: Added backlog argument.*
357
358  *Changed in version 1.5.4: Support for the context manager protocol was
359  added. Exiting the context manager is equivalent to calling
360  :meth:`close_all`.*
361
362  >>> from pyftpdlib.servers import FTPServer
363  >>> address = ('127.0.0.1', 21)
364  >>> server = FTPServer(address, handler)
365  >>> server.serve_forever()
366
367  It can also be used as a context manager. Exiting the context manager is
368  equivalent to calling :meth:`close_all`.
369
370  >>> with FTPServer(address, handler) as server:
371  ...     server.serve_forever()
372
373  .. data:: max_cons
374
375    Number of maximum simultaneous connections accepted (default ``512``).
376
377  .. data:: max_cons_per_ip
378
379    Number of maximum connections accepted for the same IP address (default
380    ``0`` == no limit).
381
382  .. method:: serve_forever(timeout=None, blocking=True, handle_exit=True, worker_processes=1)
383
384    Starts the asynchronous IO loop.
385
386    - (float) timeout: the timeout passed to the underlying IO
387      loop expressed in seconds.
388
389    - (bool) blocking: if False loop once and then return the
390      timeout of the next scheduled call next to expire soonest
391      (if any).
392
393    - (bool) handle_exit: when True catches ``KeyboardInterrupt`` and
394      ``SystemExit`` exceptions (caused by SIGTERM / SIGINT signals) and
395      gracefully exits after cleaning up resources. Also, logs server start and
396      stop.
397
398    - (int) worker_processes: pre-fork a certain number of child
399      processes before starting. See: :ref:`pre-fork-model`.
400      Each child process will keep using a 1-thread, async
401      concurrency model, handling multiple concurrent connections.
402      If the number is None or <= 0 the number of usable cores
403      available on this machine is detected and used.
404      It is a good idea to use this option in case the app risks
405      blocking for too long on a single function call (e.g.
406      hard-disk is slow, long DB query on auth etc.).
407      By splitting the work load over multiple processes the delay
408      introduced by a blocking function call is amortized and divided
409      by the number of worker processes.
410
411    *Changed in version 1.0.0*: no longer a classmethod
412
413    *Changed in version 1.0.0*: 'use_poll' and 'count' parameters were removed
414
415    *Changed in version 1.0.0*: 'blocking' and 'handle_exit' parameters were
416    added
417
418  .. method:: close()
419
420    Stop accepting connections without disconnecting currently connected
421    clients. :meth:`server_forever` loop will automatically stop when there are
422    no more connected clients.
423
424  .. method:: close_all()
425
426    Disconnect all clients, tell :meth:`server_forever` loop to stop and wait
427    until it does.
428
429    *Changed in version 1.0.0: 'map' and 'ignore_all' parameters were removed.*
430
431Filesystem
432==========
433
434.. class:: pyftpdlib.filesystems.FilesystemError
435
436  Exception class which can be raised from within
437  :class:`pyftpdlib.filesystems.AbstractedFS` in order to send custom error
438  messages to client. *New in version 1.0.0*
439
440.. class:: pyftpdlib.filesystems.AbstractedFS(root, cmd_channel)
441
442  A class used to interact with the file system, providing a cross-platform
443  interface compatible with both Windows and UNIX style filesystems where all
444  paths use ``"/"`` separator. AbstractedFS distinguishes between "real"
445  filesystem paths and "virtual" ftp paths emulating a UNIX chroot jail where
446  the user can not escape its home directory (example: real "/home/user" path
447  will be seen as "/" by the client). It also provides some utility methods and
448  wraps around all os.* calls involving operations against the filesystem like
449  creating files or removing directories. The contructor accepts two arguments:
450  root which is the user "real" home directory (e.g. '/home/user') and
451  cmd_channel which is the :class:`pyftpdlib.handlers.FTPHandler` class
452  instance.
453
454  *Changed in version 0.6.0: root and cmd_channel arguments were added.*
455
456  .. data:: root
457
458    User's home directory ("real"). *Changed in version 0.7.0: support
459    setattr()*
460
461  .. data:: cwd
462
463    User's current working directory ("virtual").
464
465    *Changed in version 0.7.0: support setattr()*
466
467  .. method:: ftpnorm(ftppath)
468
469    Normalize a "virtual" ftp pathname depending on the current working
470    directory (e.g. having ``"/foo"`` as current working directory ``"bar"``
471    becomes ``"/foo/bar"``).
472
473  .. method:: ftp2fs(ftppath)
474
475    Translate a "virtual" ftp pathname into equivalent absolute "real"
476    filesystem pathname (e.g. having ``"/home/user"`` as root directory
477    ``"foo"`` becomes ``"/home/user/foo"``).
478
479  .. method:: fs2ftp(fspath)
480
481    Translate a "real" filesystem pathname into equivalent absolute "virtual"
482    ftp pathname depending on the user's root directory (e.g. having
483    ``"/home/user"`` as root directory ``"/home/user/foo"`` becomes ``"/foo"``.
484
485  .. method:: validpath(path)
486
487    Check whether the path belongs to user's home directory. Expected argument
488    is a "real" filesystem path. If path is a symbolic link it is resolved to
489    check its real destination. Pathnames escaping from user's root directory
490    are considered not valid (return ``False``).
491
492  .. method:: open(filename, mode)
493
494    Wrapper around
495    `open() <http://docs.python.org/library/functions.html#open>`_ builtin.
496
497  .. method:: mkdir(path)
498  .. method:: chdir(path)
499  .. method:: rmdir(path)
500  .. method:: remove(path)
501  .. method:: rename(src, dst)
502  .. method:: chmod(path, mode)
503  .. method:: stat(path)
504  .. method:: lstat(path)
505  .. method:: readlink(path)
506
507    Wrappers around corresponding
508    `os <http://docs.python.org/library/os.html>`_ module functions.
509
510  .. method:: isfile(path)
511  .. method:: islink(path)
512  .. method:: isdir(path)
513  .. method:: getsize(path)
514  .. method:: getmtime(path)
515  .. method:: realpath(path)
516  .. method:: lexists(path)
517
518    Wrappers around corresponding
519    `os.path <http://docs.python.org/library/os.path.html>`_ module functions.
520
521  .. method:: mkstemp(suffix='', prefix='', dir=None, mode='wb')
522
523    Wrapper around
524    `tempfile.mkstemp <http://docs.python.org/library/tempfile.html#tempfile.mkstemp>`_.
525
526  .. method:: listdir(path)
527
528    Wrapper around
529    `os.listdir <http://docs.python.org/library/os.html#os.listdir>`_.
530    It is expected to return a list of unicode strings or a generator yielding
531    unicode strings.
532
533    .. versionchanged:: 1.6.0 can also return a generator.
534
535
536Extended classes
537================
538
539  We are about to introduces are extensions (subclasses) of the ones explained
540  so far. They usually require third-party modules to be installed separately
541  or are specific for a given Python version or operating system.
542
543Extended handlers
544-----------------
545
546.. class:: pyftpdlib.handlers.TLS_FTPHandler(conn, server)
547
548  A :class:`pyftpdlib.handlers.FTPHandler` subclass implementing FTPS (FTP over
549  SSL/TLS) as described in `RFC-4217 <http://www.faqs.org/rfcs/rfc4217.html>`_
550  implementing AUTH, PBSZ and PROT commands.
551  `PyOpenSSL <http://pypi.python.org/pypi/pyOpenSSL>`_ module is required to be
552  installed. Example below shows how to setup an FTPS server. Configurable
553  attributes:
554
555  .. data:: certfile
556
557    The path to a file which contains a certificate to be used to identify the
558    local side of the connection. This must always be specified, unless context
559    is provided instead.
560
561  .. data:: keyfile
562
563    The path of the file containing the private RSA key; can be omittetted if
564    certfile already contains the private key (defaults: ``None``).
565
566  .. data:: ssl_protocol
567
568     The desired SSL protocol version to use. This defaults to
569     `SSL.SSLv23_METHOD` which will negotiate the highest protocol that both
570     the server and your installation of OpenSSL support.
571
572  .. data:: ssl_options
573
574     specific OpenSSL options. These default to:
575     `SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_NO_COMPRESSION` disabling
576     SSLv2 and SSLv3 versions and SSL compression algorithm which are
577     considered insecure.
578     Can be set to None in order to improve compatibilty with older (insecure)
579     FTP clients.
580
581     .. versionadded:: 1.6.0
582
583  .. data:: ssl_context
584
585      A `SSL.Context <http://pyopenssl.sourceforge.net/pyOpenSSL.html/openssl-context.html>`__
586      instance which was previously configured.
587      If specified :data:`ssl_protocol` and :data:`ssl_options` parameters will
588      be ignored.
589
590  .. data:: tls_control_required
591
592    When True requires SSL/TLS to be established on the control channel, before
593    logging in. This means the user will have to issue AUTH before USER/PASS
594    (default ``False``).
595
596  .. data:: tls_data_required
597
598    When True requires SSL/TLS to be established on the data channel. This
599    means the user will have to issue PROT before PASV or PORT (default
600    ``False``).
601
602Extended authorizers
603--------------------
604
605.. 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.")
606
607  Authorizer which interacts with the UNIX password database. Users are no
608  longer supposed to be explicitly added as when using
609  :class:`pyftpdlib.authorizers.DummyAuthorizer`. All FTP users are the same
610  defined on the UNIX system so if you access on your system by using
611  ``"john"`` as username and ``"12345"`` as password those same credentials can
612  be used for accessing the FTP server as well. The user home directories will
613  be automatically determined when user logins. Every time a filesystem
614  operation occurs (e.g. a file is created or deleted) the id of the process is
615  temporarily changed to the effective user id and whether the operation will
616  succeed depends on user and file permissions. This is why full read and write
617  permissions are granted by default in the class constructors.
618
619  *global_perm* is a series of letters referencing the users permissions;
620  defaults to "elradfmwMT" which means full read and write access for everybody
621  (except anonymous). *allowed_users* and *rejected_users* options expect a
622  list of users which are accepted or rejected for authenticating against the
623  FTP server; defaults both to ``[]`` (no restrictions). *require_valid_shell*
624  denies access for those users which do not have a valid shell binary listed in
625  /etc/shells. If /etc/shells cannot be found this is a no-op. *anonymous user*
626  is not subject to this option, and is free to not have a valid shell defined.
627  Defaults to ``True`` (a valid shell is required for login). *anonymous_user*
628  can be specified if you intend to provide anonymous access. The value
629  expected is a string representing the system user to use for managing
630  anonymous sessions;
631  defaults to ``None`` (anonymous access disabled). Note that in order to use
632  this class super user privileges are required.
633
634  *New in version 0.6.0*
635
636  .. method:: override_user(username=None, password=None, homedir=None, perm=None, anonymous_user=None, msg_login=None, msg_quit=None)
637
638    Overrides one or more options specified in the class constructor for a
639    specific user. Example:
640
641    >>> from pyftpdlib.authorizers import UnixAuthorizer
642    >>> auth = UnixAuthorizer(rejected_users=["root"])
643    >>> auth = UnixAuthorizer(allowed_users=["matt", "jay"])
644    >>> auth = UnixAuthorizer(require_valid_shell=False)
645    >>> auth.override_user("matt", password="foo", perm="elr")
646
647.. 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.")
648
649  Same as :class:`pyftpdlib.authorizers.UnixAuthorizer` except for
650  *anonymous_password* argument which must be specified when defining the
651  *anonymous_user*. Also requires_valid_shell option is not available. In
652  order to use this class pywin32 extension must be installed.
653
654  *New in version 0.6.0*
655
656Extended filesystems
657--------------------
658
659.. class:: pyftpdlib.filesystems.UnixFilesystem(root, cmd_channel)
660
661  Represents the real UNIX filesystem. Differently from
662  :class:`pyftpdlib.filesystems.AbstractedFS` the client will login into
663  /home/<username> and will be able to escape its home directory and navigate
664  the real filesystem. Use it in conjuction with
665  :class:`pyftpdlib.authorizers.UnixAuthorizer` to implement a "real" UNIX FTP
666  server (see
667  `demo/unix_ftpd.py <https://github.com/giampaolo/pyftpdlib/blob/master/demo/unix_ftpd.py>`__).
668
669  *New in version 0.6.0*
670
671Extended servers
672----------------
673
674.. class:: pyftpdlib.servers.ThreadedFTPServer(address_or_socket, handler, ioloop=None, backlog=5)
675
676  A modified version of base :class:`pyftpdlib.servers.FTPServer` class which
677  spawns a thread every time a new connection is established. Differently from
678  base FTPServer class, the handler will be free to block without hanging the
679  whole IO loop. See :ref:`changing-the-concurrency-model`.
680
681  *New in version 1.0.0*
682
683  *Changed in 1.2.0: added ioloop parameter; address can also be a pre-existing
684  *socket.*
685
686.. class:: pyftpdlib.servers.MultiprocessFTPServer(address_or_socket, handler, ioloop=None, backlog=5)
687
688  A modified version of base :class:`pyftpdlib.servers.FTPServer` class which
689  spawns a process every time a new connection is established. Differently from
690  base FTPServer class, the handler will be free to block without hanging the
691  whole IO loop. See :ref:`changing-the-concurrency-model`.
692
693  *New in version 1.0.0*
694
695  *Changed in 1.2.0: added ioloop parameter; address can also be a pre-existing socket.*
696
697  *Availability: POSIX + Python >= 2.6*
698