summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/bugzilla19
-rw-r--r--bugzilla/base.py42
2 files changed, 44 insertions, 17 deletions
diff --git a/bin/bugzilla b/bin/bugzilla
index 7643c31..9623187 100755
--- a/bin/bugzilla
+++ b/bin/bugzilla
@@ -13,6 +13,7 @@
import bugzilla, optparse
import os, sys, glob, re
import logging
+import getpass
version = '0.3'
default_bz = 'https://bugzilla.redhat.com/xmlrpc.cgi'
@@ -25,7 +26,7 @@ if '--debug' in sys.argv:
elif '--verbose' in sys.argv:
log.setLevel(logging.INFO)
-cmdlist = ('info','query','new','modify')
+cmdlist = ('info','query','new','modify','login')
def setup_parser():
u = "usage: %prog [global options] COMMAND [options]"
u += "\nCommands: %s" % ', '.join(cmdlist)
@@ -189,15 +190,25 @@ if __name__ == '__main__':
# Connect to bugzilla
log.info('Connecting to %s',global_opt.bugzilla)
bz=bugzilla.Bugzilla(url=global_opt.bugzilla)
- if global_opt.user and global_opt.password:
+ if global_opt.user:
+ if not global_opt.password:
+ global_opt.password = getpass.getpass()
log.info('Using username/password for authentication')
bz.login(global_opt.user,global_opt.password)
else:
- log.info('No authentication info found.')
+ if global_opt.cookiefile:
+ bz.cookiefile = global_opt.cookiefile
+ cookiefile = bz.cookiefile
+ if os.path.exists(cookiefile):
+ log.info('Using cookies in %s for authentication', cookiefile)
+ else:
+ log.info('No authentication info found.')
# And now we actually execute the given command
buglist = list() # save the results of query/new/modify here
- if action == 'info':
+ if action == 'login':
+ pass
+ elif action == 'info':
if opt.products:
for k in sorted(bz.products):
print k
diff --git a/bugzilla/base.py b/bugzilla/base.py
index 1ec39d7..2a4d56c 100644
--- a/bugzilla/base.py
+++ b/bugzilla/base.py
@@ -39,16 +39,14 @@ class BugzillaBase(object):
instance. Uses xmlrpclib to do its thing. You'll want to create one thusly:
bz=Bugzilla(url='https://bugzilla.redhat.com/xmlrpc.cgi',user=u,password=p)
- If you so desire, you can use cookie headers for authentication instead.
- So you could do:
- cf=glob(os.path.expanduser('~/.mozilla/firefox/default.*/cookies.txt'))
- bz=Bugzilla(url=url,cookies=cf)
- and, assuming you have previously logged info bugzilla with firefox, your
- pre-existing auth cookie would be used, thus saving you the trouble of
- stuffing your username and password in the bugzilla call.
- On the other hand, this currently munges up the cookie so you'll have to
- log back in when you next use bugzilla in firefox. So this is not
- currently recommended.
+ You can get authentication cookies by calling the login() method. These
+ cookies will be stored in a MozillaCookieJar-style file specified by the
+ 'cookiefile' attribute (which defaults to ~/.bugzillacookies).
+
+ You can also specify 'user' and 'password' in a bugzillarc file, either
+ /etc/bugzillarc or ~/.bugzillarc. The latter will override the former.
+ Be sure to set appropriate permissions on those files if you choose to
+ store your password in one of them!
The methods which start with a single underscore are thin wrappers around
xmlrpc calls; those should be safe for multicall usage.
@@ -62,6 +60,7 @@ class BugzillaBase(object):
self.user = ''
self.password = ''
self.url = ''
+ self.cookiefile = os.path.expanduser('~/.bugzillacookies')
self.user_agent = user_agent
self.logged_in = False
# Bugzilla object state info that users shouldn't mess with
@@ -83,6 +82,18 @@ class BugzillaBase(object):
#---- Methods for establishing bugzilla connection and logging in
+ def initcookiefile(self,cookiefile=None):
+ '''Read the given (Mozilla-style) cookie file and fill in the
+ cookiejar, allowing us to use saved credentials to access Bugzilla.
+ If no file is given, self.cookiefile will be used.'''
+ if cookiefile:
+ self.cookiefile = cookiefile
+ cj = cookielib.MozillaCookieJar(self.cookiefile)
+ if os.path.exists(self.cookiefile):
+ cj.load()
+ self._cookiejar = cj
+ self._cookiejar.filename = self.cookiefile
+
configpath = ['/etc/bugzillarc','~/.bugzillarc']
def readconfig(self,configpath=None):
'''Read bugzillarc file(s) into memory.'''
@@ -119,12 +130,13 @@ class BugzillaBase(object):
you'll have to login() yourself before some methods will work.
'''
# Set up the transport
+ self.initcookiefile()
if url.startswith('https'):
self._transport = SafeCookieTransport()
else:
self._transport = CookieTransport()
self._transport.user_agent = self.user_agent
- self._transport.cookiejar = self._cookiejar or cookielib.CookieJar()
+ self._transport.cookiejar = self._cookiejar
# Set up the proxy, using the transport
self._proxy = xmlrpclib.ServerProxy(url,self._transport)
# Set up the urllib2 opener (using the same cookiejar)
@@ -693,7 +705,7 @@ class CookieTransport(xmlrpclib.Transport):
# Cribbed from xmlrpclib.Transport.send_user_agent
def send_cookies(self, connection, cookie_request):
if self.cookiejar is None:
- log.debug("send_cookies(): creating cookiejar")
+ log.debug("send_cookies(): creating in-memory cookiejar")
self.cookiejar = cookielib.CookieJar()
elif self.cookiejar:
log.debug("send_cookies(): using existing cookiejar")
@@ -740,7 +752,11 @@ class CookieTransport(xmlrpclib.Transport):
log.debug("cookiejar now contains: %s" % self.cookiejar._cookies)
# And write back any changes
if hasattr(self.cookiejar,'save'):
- self.cookiejar.save(self.cookiejar.filename)
+ try:
+ self.cookiejar.save(self.cookiejar.filename)
+ except e:
+ log.error("Couldn't write cookiefile %s: %s" % \
+ (self.cookiejar.filename,str(e))
if errcode != 200:
raise xmlrpclib.ProtocolError(