[Python-checkins] r70391 - tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py
martin.v.loewis
python-checkins at python.org
Sun Mar 15 22:44:44 CET 2009
Author: martin.v.loewis
Date: Sun Mar 15 22:44:43 2009
New Revision: 70391
Log:
Add 1.4.7 file missing in previous commit.
Added:
tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py (contents, props changed)
Added: tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py
==============================================================================
--- (empty file)
+++ tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py Sun Mar 15 22:44:43 2009
@@ -0,0 +1,175 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007 Stefan Seefeld
+# All rights reserved.
+# For license terms see the file COPYING.txt.
+#
+
+import base64, getopt, os, sys, socket, urllib
+from roundup.xmlrpc import translate
+from roundup.xmlrpc import RoundupInstance
+import roundup.instance
+from roundup.instance import TrackerError
+from roundup.cgi.exceptions import Unauthorised
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
+
+
+class RequestHandler(SimpleXMLRPCRequestHandler):
+ """A SimpleXMLRPCRequestHandler with support for basic
+ HTTP Authentication."""
+
+ TRACKER_HOMES = {}
+ TRACKERS = {}
+
+ def is_rpc_path_valid(self):
+ path = self.path.split('/')
+ name = urllib.unquote(path[1]).lower()
+ return name in self.TRACKER_HOMES
+
+ def get_tracker(self, name):
+ """Return a tracker instance for given tracker name."""
+
+ if name in self.TRACKERS:
+ return self.TRACKERS[name]
+
+ if name not in self.TRACKER_HOMES:
+ raise Exception('No such tracker "%s"'%name)
+ tracker_home = self.TRACKER_HOMES[name]
+ tracker = roundup.instance.open(tracker_home)
+ self.TRACKERS[name] = tracker
+ return tracker
+
+
+ def authenticate(self, tracker):
+
+
+ # Try to extract username and password from HTTP Authentication.
+ username, password = None, None
+ authorization = self.headers.get('authorization', ' ')
+ scheme, challenge = authorization.split(' ', 1)
+
+ if scheme.lower() == 'basic':
+ decoded = base64.decodestring(challenge)
+ if ':' in decoded:
+ username, password = decoded.split(':')
+ else:
+ username = decoded
+ if not username:
+ username = 'anonymous'
+ db = tracker.open('admin')
+ try:
+ userid = db.user.lookup(username)
+ except KeyError: # No such user
+ db.close()
+ raise Unauthorised, 'Invalid user'
+ stored = db.user.get(userid, 'password')
+ if stored != password:
+ # Wrong password
+ db.close()
+ raise Unauthorised, 'Invalid user'
+ db.setCurrentUser(username)
+ return db
+
+
+ def do_POST(self):
+ """Extract username and password from authorization header."""
+
+ db = None
+ try:
+ path = self.path.split('/')
+ tracker_name = urllib.unquote(path[1]).lower()
+ tracker = self.get_tracker(tracker_name)
+ db = self.authenticate(tracker)
+
+ instance = RoundupInstance(db, tracker.actions, None)
+ self.server.register_instance(instance)
+ SimpleXMLRPCRequestHandler.do_POST(self)
+ except Unauthorised, message:
+ self.send_error(403, '%s (%s)'%(self.path, message))
+ except:
+ if db:
+ db.close()
+ exc, val, tb = sys.exc_info()
+ print exc, val, tb
+ raise
+ if db:
+ db.close()
+
+
+class Server(SimpleXMLRPCServer):
+
+ def _dispatch(self, method, params):
+
+ retn = SimpleXMLRPCServer._dispatch(self, method, params)
+ retn = translate(retn)
+ return retn
+
+
+def usage():
+ print """Usage: %s: [options] [name=tracker home]+
+
+Options:
+ -e, --encoding -- specify the encoding to use
+ -V -- be verbose when importing
+ -p, --port <port> -- port to listen on
+
+"""%sys.argv[0]
+
+def run():
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],
+ 'e:i:p:V', ['encoding=', 'port='])
+ except getopt.GetoptError, e:
+ usage()
+ return 1
+
+ verbose = False
+ port = 8000
+ encoding = None
+
+ for opt, arg in opts:
+ if opt == '-V':
+ verbose = True
+ elif opt in ['-p', '--port']:
+ port = int(arg)
+ elif opt in ['-e', '--encoding']:
+ encoding = encoding
+
+ tracker_homes = {}
+ for arg in args:
+ try:
+ name, home = arg.split('=', 1)
+ # Validate the argument
+ tracker = roundup.instance.open(home)
+ except ValueError:
+ print 'Instances must be name=home'
+ sys.exit(-1)
+ except TrackerError:
+ print 'Tracker home does not exist.'
+ sys.exit(-1)
+
+ tracker_homes[name] = home
+
+ RequestHandler.TRACKER_HOMES=tracker_homes
+
+ if sys.version_info[0:2] < (2,5):
+ if encoding:
+ print 'encodings not supported with python < 2.5'
+ sys.exit(-1)
+ server = Server(('', port), RequestHandler)
+ else:
+ server = Server(('', port), RequestHandler,
+ allow_none=True, encoding=encoding)
+
+ # Go into the main listener loop
+ print 'Roundup XMLRPC server started on %s:%d' \
+ % (socket.gethostname(), port)
+ try:
+ server.serve_forever()
+ except KeyboardInterrupt:
+ print 'Keyboard Interrupt: exiting'
+
+if __name__ == '__main__':
+ run()
More information about the Python-checkins
mailing list