Skip to content

Commit

Permalink
Merge remote branch 'jjongsma/http-auth'
Browse files Browse the repository at this point in the history
  • Loading branch information
owtaylor committed Sep 6, 2010
2 parents 55d8141 + 5c52c2f commit ca9301d
Showing 1 changed file with 84 additions and 13 deletions.
97 changes: 84 additions & 13 deletions git-bz
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import traceback
import xmlrpclib import xmlrpclib
import urlparse import urlparse
from xml.etree.cElementTree import ElementTree from xml.etree.cElementTree import ElementTree
import base64


# Globals # Globals
# ======= # =======
Expand Down Expand Up @@ -334,6 +335,24 @@ def tracker_uses_https(tracker):
config = get_config(tracker) config = get_config(tracker)
return 'https' in config and config['https'] == 'true' return 'https' in config and config['https'] == 'true'


def tracker_get_path(tracker):
config = get_config(tracker)
if 'path' in config:
return config['path']
return None

def tracker_get_auth_user(tracker):
config = get_config(tracker)
if 'path' in config:
return config['authuser']
return None

def tracker_get_auth_password(tracker):
config = get_config(tracker)
if 'path' in config:
return config['authpwd']
return None

def get_default_fields(tracker): def get_default_fields(tracker):
config = get_config(tracker) config = get_config(tracker)


Expand All @@ -356,23 +375,58 @@ class BugParseError(Exception):
# uniquely identifies a bug on a server, though until we try # uniquely identifies a bug on a server, though until we try
# to load it (and create a Bug) we don't know if it actually exists. # to load it (and create a Bug) we don't know if it actually exists.
class BugHandle: class BugHandle:
def __init__(self, host, https, id): def __init__(self, host, path, https, id, authuser=None, authpwd=None):
self.host = host self.host = host
self.path = path
self.https = https self.https = https
self.id = id self.id = id
self.authuser = authuser
self.authpwd = authpwd

# ensure that the path to the bugzilla installation is an absolute path
# so that it will still work even if their config option specifies
# something like:
# path = bugzilla
# instead of the proper form:
# path = /bugzilla
if self.path and self.path[0] != '/':
self.path = '/' + self.path


def get_url(self): def get_url(self):
return "%s://%s/show_bug.cgi?id=%s" % ("https" if self.https else "http", return "%s://%s/show_bug.cgi?id=%s" % ("https" if self.https else "http",
self.host, self.host,
self.id) self.id)


def needs_auth(self):
return self.authuser and self.authpwd

@staticmethod @staticmethod
def parse(bug_reference): def parse(bug_reference):
m = re.match("http(s?)://([^/]+)/show_bug.cgi\?id=([^&]+)", bug_reference) parseresult = urlparse.urlsplit (bug_reference)
if m:
return BugHandle(host=m.group(2), if parseresult.scheme in ('http', 'https'):
https=m.group(1) != "", user = parseresult.username
id=m.group(3)) pwd = parseresult.password
# if the url did not specify http auth credentials in the form
# https://user:pwd@host.com, check to see whether the config file
# specifies any auth credentials for this host
if not user:
user = tracker_get_auth_user(parseresult.hostname)
if not pwd:
pwd = tracker_get_auth_password(parseresult.hostname)

# strip off everything after the last '/', so '/bugzilla/show_bug.cgi'
# will simply become '/bugzilla'
path = parseresult.path[:parseresult.path.rfind('/')]
m = re.match("id=([^&]+)", parseresult.query)

if m:
return BugHandle(host=parseresult.hostname,
path=path,
https=parseresult.scheme=="https",
id=m.group(1),
authuser=user,
authpwd=pwd)


colon = bug_reference.find(":") colon = bug_reference.find(":")
if colon > 0: if colon > 0:
Expand All @@ -387,11 +441,14 @@ class BugHandle:


host = resolve_host_alias(tracker) host = resolve_host_alias(tracker)
https = tracker_uses_https(tracker) https = tracker_uses_https(tracker)
path = tracker_get_path(tracker)
authuser = tracker_get_auth_user(tracker)
authpwd = tracker_get_auth_password(tracker)


if not re.match(r"^.*\.[a-zA-Z]{2,}$", host): if not re.match(r"^.*\.[a-zA-Z]{2,}$", host):
raise BugParseError("'%s' doesn't look like a valid bugzilla host or alias" % host) raise BugParseError("'%s' doesn't look like a valid bugzilla host or alias" % host)


return BugHandle(host=host, https=https, id=id) return BugHandle(host=host, path=path, https=https, id=id, authuser=authuser, authpwd=authpwd)


@staticmethod @staticmethod
def parse_or_die(str): def parse_or_die(str):
Expand Down Expand Up @@ -728,6 +785,9 @@ def die(message):
print >>sys.stderr, message print >>sys.stderr, message
sys.exit(1) sys.exit(1)


def http_auth_header(user, password):
return 'Basic ' + base64.encodestring("%s:%s" % (user, password)).strip()

# Classes for bug handling # Classes for bug handling
# ======================== # ========================


Expand All @@ -753,9 +813,12 @@ def get_connection(host, https):
return connections[identifier] return connections[identifier]


class BugServer(object): class BugServer(object):
def __init__(self, host, https): def __init__(self, host, path, https, authuser=None, authpwd=None):
self.host = host self.host = host
self.path = path
self.https = https self.https = https
self.authuser = authuser
self.authpwd = authpwd


self.cookies = get_bugzilla_cookies(host) self.cookies = get_bugzilla_cookies(host)


Expand All @@ -769,6 +832,10 @@ class BugServer(object):
headers = dict(headers) headers = dict(headers)
headers['Cookie'] = self.get_cookie_string() headers['Cookie'] = self.get_cookie_string()
headers['User-Agent'] = "git-bz" headers['User-Agent'] = "git-bz"
if self.authuser and self.authpwd:
headers['Authorization'] = http_auth_header(self.authuser, self.authpwd)
if self.path:
url = self.path + url


seen_urls = [] seen_urls = []
connection = get_connection(self.host, self.https) connection = get_connection(self.host, self.https)
Expand Down Expand Up @@ -891,17 +958,18 @@ class BugTransport(xmlrpclib.Transport):
def send_request(self, connection, *args): def send_request(self, connection, *args):
xmlrpclib.Transport.send_request(self, connection, *args) xmlrpclib.Transport.send_request(self, connection, *args)
connection.putheader("Cookie", self.server.get_cookie_string()) connection.putheader("Cookie", self.server.get_cookie_string())
connection.putheader("Authorization", http_auth_header(self.server.authuser, self.server.authpwd))


servers = {} servers = {}


# Note that if we detect that we are redirecting, we may rewrite the # Note that if we detect that we are redirecting, we may rewrite the
# host/https of the server to avoid doing too many redirections, and # host/https of the server to avoid doing too many redirections, and
# so the host,https we connect to may be different than what we use # so the host,https we connect to may be different than what we use
# to look up the server. # to look up the server.
def get_bug_server(host, https): def get_bug_server(host, path, https, authuser, authpwd):
identifier = (host, https) identifier = (host, path, https)
if not identifier in servers: if not identifier in servers:
servers[identifier] = BugServer(host, https) servers[identifier] = BugServer(host, path, https, authuser, authpwd)


return servers[identifier] return servers[identifier]


Expand Down Expand Up @@ -1149,7 +1217,7 @@ class Bug(object):


@staticmethod @staticmethod
def load(bug_reference, attachmentdata=False): def load(bug_reference, attachmentdata=False):
server = get_bug_server(bug_reference.host, bug_reference.https) server = get_bug_server(bug_reference.host, bug_reference.path, bug_reference.https, bug_reference.authuser, bug_reference.authpwd)
bug = Bug(server) bug = Bug(server)
bug._load(bug_reference.id, attachmentdata) bug._load(bug_reference.id, attachmentdata)


Expand All @@ -1159,9 +1227,12 @@ class Bug(object):
def create(tracker, product, component, short_desc, comment): def create(tracker, product, component, short_desc, comment):
host = resolve_host_alias(tracker) host = resolve_host_alias(tracker)
https = tracker_uses_https(tracker) https = tracker_uses_https(tracker)
path = tracker_get_path(tracker)
authuser = tracker_get_auth_user(tracker)
authpwd = tracker_get_auth_password(tracker)
default_fields = get_default_fields(tracker) default_fields = get_default_fields(tracker)


server = get_bug_server(host, https) server = get_bug_server(host, path, https, authuser, authpwd)
bug = Bug(server) bug = Bug(server)
bug._create(product, component, short_desc, comment, default_fields) bug._create(product, component, short_desc, comment, default_fields)


Expand Down

0 comments on commit ca9301d

Please sign in to comment.