diff --git a/deluge/core/authmanager.py b/deluge/core/authmanager.py index 54ec0b1d8..9f31321cd 100644 --- a/deluge/core/authmanager.py +++ b/deluge/core/authmanager.py @@ -1,37 +1,11 @@ -# -# authmanager.py +# -*- coding: utf-8 -*- # # Copyright (C) 2009 Andrew Resch # Copyright (C) 2011 Pedro Algarvio # -# Deluge is free software. -# -# You may redistribute it and/or modify it under the terms of the -# GNU General Public License, as published by the Free Software -# Foundation; either version 3 of the License, or (at your option) -# any later version. -# -# deluge is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with deluge. If not, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. -# +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. # import os @@ -111,18 +85,18 @@ class AuthManager(component.Component): self.__load_auth_file() def authorize(self, username, password): - """ - Authorizes users based on username and password + """Authorizes users based on username and password. - :param username: str, username - :param password: str, password - :returns: int, the auth level for this user - :rtype: int + Args: + username (str): Username + password (str): Password - :raises AuthenticationRequired: if aditional details are required to - authenticate. - :raises BadLoginError: if the username does not exist or password does - not match. + Returns: + int: The auth level for this user. + + Raises: + AuthenticationRequired: If aditional details are required to authenticate. + BadLoginError: If the username does not exist or password does not match. """ if not username: @@ -148,9 +122,7 @@ class AuthManager(component.Component): return username in self.__auth def get_known_accounts(self): - """ - Returns a list of known deluge usernames. - """ + """Returns a list of known deluge usernames.""" self.__load_auth_file() return [account.data() for account in self.__auth.values()] @@ -256,16 +228,11 @@ class AuthManager(component.Component): if line.startswith("#") or not line: # This line is a comment or empty continue - try: - lsplit = line.split(":") - except Exception, e: - log.error("Your auth file is malformed: %s", e) - continue + lsplit = line.split(":") if len(lsplit) == 2: username, password = lsplit log.warning("Your auth entry for %s contains no auth level, " - "using AUTH_LEVEL_DEFAULT(%s)..", username, - AUTH_LEVEL_DEFAULT) + "using AUTH_LEVEL_DEFAULT(%s)..", username, AUTH_LEVEL_DEFAULT) if username == 'localclient': authlevel = AUTH_LEVEL_ADMIN else: @@ -275,8 +242,7 @@ class AuthManager(component.Component): elif len(lsplit) == 3: username, password, authlevel = lsplit else: - log.error("Your auth file is malformed: " - "Incorrect number of fields!") + log.error("Your auth file is malformed: Incorrect number of fields!") continue username = username.strip() @@ -287,8 +253,7 @@ class AuthManager(component.Component): try: authlevel = AUTH_LEVELS_MAPPING[authlevel] except KeyError: - log.error("Your auth file is malformed: %r is not a valid auth " - "level" % authlevel) + log.error("Your auth file is malformed: %r is not a valid auth level", authlevel) continue self.__auth[username] = Account(username, password, authlevel) diff --git a/deluge/core/daemon.py b/deluge/core/daemon.py index 93aba8bb1..413ea7529 100644 --- a/deluge/core/daemon.py +++ b/deluge/core/daemon.py @@ -1,36 +1,14 @@ -# -# daemon.py +# -*- coding: utf-8 -*- # # Copyright (C) 2007-2009 Andrew Resch # -# Deluge is free software. -# -# You may redistribute it and/or modify it under the terms of the -# GNU General Public License, as published by the Free Software -# Foundation; either version 3 of the License, or (at your option) -# any later version. -# -# deluge is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with deluge. If not, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. # + +"""The Deluge daemon""" + import os import logging from twisted.internet import reactor @@ -50,7 +28,7 @@ log = logging.getLogger(__name__) def check_running_daemon(pid_file): - """Check for another running instance of the daemon using the same pid file""" + """Check for another running instance of the daemon using the same pid file.""" if os.path.isfile(pid_file): # Get the PID and the port of the supposedly running daemon with open(pid_file) as _file: @@ -61,6 +39,7 @@ def check_running_daemon(pid_file): pid, port = None, None def process_running(pid): + """Verify if pid is a running process.""" if windows_check(): from win32process import EnumProcesses return pid in EnumProcesses() @@ -89,10 +68,19 @@ def check_running_daemon(pid_file): class Daemon(object): - def __init__(self, options=None, args=None, classic=False): + """The Deluge Daemon class""" + + def __init__(self, listen_interface=None, interface=None, port=None, classic=False): + """ + Args: + listen_interface (str, optional): The IP address to listen to bittorrent connections on. + interface (str, optional): The IP address the daemon will listen for UI connections on. + port (int, optional): The port the daemon will listen for UI connections on. + classic (bool, optional): If True the client is in Classic (Standalone) mode otherwise, if + False, start the daemon as separate process. + + """ log.info("Deluge daemon %s", get_version()) - log.debug("options: %s", options) - log.debug("args: %s", args) pid_file = get_config_dir("deluged.pid") check_running_daemon(pid_file) @@ -103,26 +91,24 @@ class Daemon(object): # Catch some Windows specific signals if windows_check(): def win_handler(ctrl_type): + """Handle the Windows shutdown or close events.""" log.debug("windows handler ctrl_type: %s", ctrl_type) if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT: self._shutdown() return 1 SetConsoleCtrlHandler(win_handler) - listen_interface = None - if options and options.listen_interface and is_ip(options.listen_interface): - listen_interface = options.listen_interface + if listen_interface and not is_ip(listen_interface): + listen_interface = None # Start the core as a thread and join it until it's done self.core = Core(listen_interface=listen_interface) - port = self.core.config["daemon_port"] - if options and options.port: - port = options.port + if port is None: + port = self.core.config["daemon_port"] - interface = None - if options and options.ui_interface: - interface = options.ui_interface + if interface and not is_ip(interface): + interface = None self.rpcserver = RPCServer( port=port, @@ -131,6 +117,8 @@ class Daemon(object): interface=interface ) + log.debug("Listening to UI on: %s:%s and bittorrent on: %s", interface, port, listen_interface) + # Register the daemon and the core RPCs self.rpcserver.register_object(self.core) self.rpcserver.register_object(self) @@ -167,22 +155,20 @@ class Daemon(object): @export() def get_method_list(self): - """ - Returns a list of the exported methods. - """ + """Returns a list of the exported methods.""" return self.rpcserver.get_method_list() @export(1) def authorized_call(self, rpc): - """ - Returns True if authorized to call rpc. + """Determines if session auth_level is authorized to call RPC. - :param rpc: a rpc, eg, "core.get_torrents_status" - :type rpc: string + Args: + rpc (str): A RPC, e.g. core.get_torrents_status + Returns: + bool: True if authorized to call RPC, otherwise False. """ if not rpc in self.get_method_list(): return False - auth_level = self.rpcserver.get_session_auth_level() - return auth_level >= self.rpcserver.get_rpc_auth_level(rpc) + return self.rpcserver.get_session_auth_level() >= self.rpcserver.get_rpc_auth_level(rpc) diff --git a/deluge/main.py b/deluge/main.py index 2a747e97f..add84bf9e 100644 --- a/deluge/main.py +++ b/deluge/main.py @@ -251,10 +251,12 @@ this should be an IP address", metavar="IFACE", options.group = grp.getgrnam(options.group)[2] os.setuid(options.group) - def run_daemon(options, args): + def run_daemon(options): from deluge.core.daemon import Daemon try: - Daemon(options, args) + Daemon(listen_interface=options.listen_interface, + interface=options.ui_interface, + port=options.port) except Exception as ex: log.exception(ex) sys.exit(1) @@ -275,6 +277,6 @@ this should be an IP address", metavar="IFACE", from twisted.internet import reactor reactor.addSystemEventTrigger("before", "shutdown", save_profile_stats) print "Running with profiler..." - profiler.runcall(run_daemon, options, args) + profiler.runcall(run_daemon, options) else: - run_daemon(options, args) + run_daemon(options)