PobHelp/ftpdlib/__main__.py
# Copyright (C) 2007 Giampaolo Rodola' <g.rodola@gmail.com>.
# Use of this source code is governed by MIT license that can be
# found in the LICENSE file.
"""
Start a stand alone anonymous FTP server from the command line as in:
$ python -m pyftpdlib
"""
import logging
import optparse
import os
import sys
from . import __ver__
from ._compat import getcwdu
from .authorizers import DummyAuthorizer
from .handlers import FTPHandler
from .log import config_logging
from .servers import FTPServer
class CustomizedOptionFormatter(optparse.IndentedHelpFormatter):
"""Formats options shown in help in a prettier way."""
def format_option(self, option):
result = []
opts = self.option_strings[option]
result.append(' %s\n' % opts)
if option.help:
help_text = ' %s\n\n' % self.expand_default(option)
result.append(help_text)
return ''.join(result)
def main():
"""Start a stand alone anonymous FTP server."""
usage = "python -m pyftpdlib [options]"
parser = optparse.OptionParser(usage=usage, description=main.__doc__,
formatter=CustomizedOptionFormatter())
parser.add_option('-i', '--interface', default=None, metavar="ADDRESS",
help="specify the interface to run on (default all "
"interfaces)")
parser.add_option('-p', '--port', type="int", default=2121, metavar="PORT",
help="specify port number to run on (default 2121)")
parser.add_option('-w', '--write', action="store_true", default=False,
help="grants write access for logged in user "
"(default read-only)")
parser.add_option('-d', '--directory', default=getcwdu(), metavar="FOLDER",
help="specify the directory to share (default current "
"directory)")
parser.add_option('-n', '--nat-address', default=None, metavar="ADDRESS",
help="the NAT address to use for passive connections")
parser.add_option('-r', '--range', default=None, metavar="FROM-TO",
help="the range of TCP ports to use for passive "
"connections (e.g. -r 8000-9000)")
parser.add_option('-D', '--debug', action='store_true',
help="enable DEBUG logging level")
parser.add_option('-v', '--version', action='store_true',
help="print pyftpdlib version and exit")
parser.add_option('-V', '--verbose', action='store_true',
help="activate a more verbose logging")
parser.add_option('-u', '--username', type=str, default=None,
help="specify username to login with (anonymous login "
"will be disabled and password required "
"if supplied)")
parser.add_option('-P', '--password', type=str, default=None,
help="specify a password to login with (username "
"required to be useful)")
options, args = parser.parse_args()
if options.version:
sys.exit("pyftpdlib %s" % __ver__)
if options.debug:
config_logging(level=logging.DEBUG)
passive_ports = None
if options.range:
try:
start, stop = options.range.split('-')
start = int(start)
stop = int(stop)
except ValueError:
parser.error('invalid argument passed to -r option')
else:
passive_ports = list(range(start, stop + 1))
# On recent Windows versions, if address is not specified and IPv6
# is installed the socket will listen on IPv6 by default; in this
# case we force IPv4 instead.
if os.name in ('nt', 'ce') and not options.interface:
options.interface = '0.0.0.0'
authorizer = DummyAuthorizer()
perm = options.write and "elradfmwMT" or "elr"
if options.username:
if not options.password:
parser.error(
"if username (-u) is supplied, password ('-P') is required")
authorizer.add_user(options.username,
options.password,
options.directory,
perm=perm)
else:
authorizer.add_anonymous(options.directory, perm=perm)
handler = FTPHandler
handler.authorizer = authorizer
handler.masquerade_address = options.nat_address
handler.passive_ports = passive_ports
ftpd = FTPServer((options.interface, options.port), FTPHandler)
# On Windows specify a timeout for the underlying select() so
# that the server can be interrupted with CTRL + C.
try:
ftpd.serve_forever(timeout=2 if os.name == 'nt' else None)
finally:
ftpd.close_all()
if __name__ == '__main__':
main()