=== modified file 'debian/control' --- debian/control 2011-11-21 15:47:12 +0000 +++ debian/control 2012-01-25 16:09:33 +0000 @@ -17,7 +17,7 @@ Architecture: all Depends: ${python:Depends}, ${misc:Depends}, python, python-apt (>= 0.6.20ubuntu16), lsb-release, python-gnupginterface, - unattended-upgrades, iso-codes + unattended-upgrades, iso-codes, python-pycurl Description: manage the repositories that you install software from This software provides an abstraction of the used apt repositories. It allows you to easily manage your distribution and independent software === modified file 'softwareproperties/ppa.py' --- softwareproperties/ppa.py 2011-11-21 15:47:12 +0000 +++ softwareproperties/ppa.py 2012-01-25 16:25:05 +0000 @@ -24,13 +24,13 @@ import re import subprocess from threading import Thread -import urllib -from urllib2 import urlopen, Request, URLError -from urlparse import urlparse +import pycurl DEFAULT_KEYSERVER = "hkp://keyserver.ubuntu.com:80/" # maintained until 2015 LAUNCHPAD_PPA_API = 'https://launchpad.net/api/1.0/~%s/+archive/%s' +# None means use pycurl default +LAUNCHPAD_PPA_CERT = None def encode(s): return re.sub("[^a-zA-Z0-9_-]","_", s) @@ -56,13 +56,30 @@ sourceslistd, encode(ppa_owner), encode(ppa_name), distro_codename) return (line, filename) +class CurlCallback: + def __init__(self): + self.contents = '' + + def body_callback(self, buf): + self.contents = self.contents + buf + def get_ppa_info_from_lp(owner_name, ppa_name): lp_url = LAUNCHPAD_PPA_API % (owner_name, ppa_name) # we ask for a JSON structure from lp_page, we could use # simplejson, but the format is simple enough for the regexp - req = Request(lp_url) - req.add_header("Accept","application/json") - lp_page = urlopen(req).read() + callback = CurlCallback() + curl = pycurl.Curl() + curl.setopt(pycurl.SSL_VERIFYPEER, 1) + curl.setopt(pycurl.SSL_VERIFYHOST, 2) + curl.setopt(pycurl.WRITEFUNCTION, callback.body_callback) + # only useful for testing + if LAUNCHPAD_PPA_CERT: + curl.setopt(pycurl.CAINFO, LAUNCHPAD_PPA_CERT) + curl.setopt(pycurl.URL, str(lp_url)) + curl.setopt(pycurl.HTTPHEADER, ["Accept: application/json"]) + curl.perform() + curl.close() + lp_page = callback.contents return json.loads(lp_page) class AddPPASigningKeyThread(Thread): @@ -86,8 +103,8 @@ owner_name, ppa_name, distro = ppa_path[1:].split('/') try: ppa_info = get_ppa_info_from_lp(owner_name, ppa_name) - except URLError as e: - print "Error reading %s: %s" % (lp_url, e) + except pycurl.error as e: + print "Error reading %s: %s" % (lp_url, e[1]) return False try: signing_key_fingerprint = ppa_info["signing_key_fingerprint"] === added file 'tests/test_lp.py' --- tests/test_lp.py 1970-01-01 00:00:00 +0000 +++ tests/test_lp.py 2012-01-25 16:24:53 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/python + +import pycurl +import unittest +import sys +sys.path.insert(0, "..") + +import softwareproperties.ppa + +class TestLP(unittest.TestCase): + + def test_ppa_info_from_lp(self): + # use correct data + info = softwareproperties.ppa.get_ppa_info_from_lp("mvo", "ppa") + self.assertNotEqual(info, {}) + self.assertEqual(info["name"], "ppa") + # use empty CERT file + softwareproperties.ppa.LAUNCHPAD_PPA_CERT = "/dev/null" + self.assertRaises( + pycurl.error, softwareproperties.ppa.get_ppa_info_from_lp, "mvo", "ppa") + + + + +if __name__ == "__main__": + unittest.main()