Add support for a basic auth transport and handler in rpcserver

This commit is contained in:
Andrew Resch 2008-12-09 02:12:37 +00:00
parent ab56257b49
commit 819ab070b4
2 changed files with 69 additions and 12 deletions

View File

@ -25,8 +25,9 @@
import gobject
import deluge.SimpleXMLRPCServer as SimpleXMLRPCServer
from deluge.SimpleXMLRPCServer import SimpleXMLRPCServer
from SocketServer import ThreadingMixIn
from base64 import decodestring, encodestring
from deluge.log import LOG as log
import deluge.component as component
@ -36,7 +37,7 @@ def export(func):
func._rpcserver_export = True
return func
class RPCServer(ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer, component.Component):
class RPCServer(component.Component):
def __init__(self, port):
component.Component.__init__(self, "RPCServer")
@ -53,24 +54,27 @@ class RPCServer(ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer, component
# Setup the xmlrpc server
try:
log.info("Starting XMLRPC server on port %s", port)
SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(
self, (hostname, port), logRequests=False, allow_none=True)
except:
log.info("Starting XMLRPC server %s:%s", hostname, port)
self.server = XMLRPCServer((hostname, port),
requestHandler=BasicAuthXMLRPCRequestHandler,
logRequests=False,
allow_none=True)
except Exception, e:
log.info("Daemon already running or port not available..")
log.error(e)
sys.exit(0)
self.register_multicall_functions()
self.register_introspection_functions()
self.server.register_multicall_functions()
self.server.register_introspection_functions()
self.socket.setblocking(False)
self.server.socket.setblocking(False)
gobject.io_add_watch(self.socket.fileno(), gobject.IO_IN | gobject.IO_OUT | gobject.IO_PRI | gobject.IO_ERR | gobject.IO_HUP, self._on_socket_activity)
gobject.io_add_watch(self.server.socket.fileno(), gobject.IO_IN | gobject.IO_OUT | gobject.IO_PRI | gobject.IO_ERR | gobject.IO_HUP, self._on_socket_activity)
def _on_socket_activity(self, source, condition):
"""This gets called when there is activity on the socket, ie, data to read
or to write."""
self.handle_request()
self.server.handle_request()
return True
def register_object(self, obj, name=None):
@ -82,8 +86,9 @@ class RPCServer(ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer, component
continue
if getattr(getattr(obj, d), '_rpcserver_export', False):
log.debug("Registering method: %s", name + "." + d)
self.register_function(getattr(obj, d), name + "." + d)
self.server.register_function(getattr(obj, d), name + "." + d)
class XMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
def get_request(self):
"""Get the request and client address from the socket.
We override this so that we can get the ip address of the client.
@ -91,3 +96,13 @@ class RPCServer(ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer, component
request, client_address = self.socket.accept()
self.client_address = client_address[0]
return (request, client_address)
class BasicAuthXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def do_POST(self):
auth = self.headers['authorization']
auth = auth.replace("Basic ","")
decoded_auth = decodestring(auth)
# Check authentication here
# if cannot authenticate, end the connection or
# otherwise call original
return SimpleXMLRPCRequestHandler.do_POST(self)

View File

@ -27,6 +27,7 @@
import os.path
import socket
import struct
import httplib
import gobject
@ -37,6 +38,47 @@ import deluge.error
from deluge.log import LOG as log
class Transport(xmlrpclib.Transport):
def __init__(self, username=None, password=None, use_datetime=0):
self.__username = username
self.__password = password
self._use_datetime = use_datetime
def request(self, host, handler, request_body, verbose=0):
# issue XML-RPC request
h = self.make_connection(host)
if verbose:
h.set_debuglevel(1)
self.send_request(h, handler, request_body)
self.send_host(h, host)
self.send_user_agent(h)
if self.__username is not None and self.__password is not None:
h.putheader("AUTHORIZATION", "Basic %s" % string.replace(
encodestring("%s:%s" % (self.__username, self.__password)),
"\012", ""))
self.send_content(h, request_body)
errcode, errmsg, headers = h.getreply()
if errcode != 200:
raise ProtocolError(
host + handler,
errcode, errmsg,
headers
)
self.verbose = verbose
try:
sock = h._conn.sock
except AttributeError:
sock = None
return self._parse_response(h.getfile(), sock)
def make_connection(self, host):
# create a HTTP connection object from a host descriptor
import httplib