diff options
Diffstat (limited to 'lib/python/debian_support.py')
-rw-r--r-- | lib/python/debian_support.py | 104 |
1 files changed, 74 insertions, 30 deletions
diff --git a/lib/python/debian_support.py b/lib/python/debian_support.py index b6e5134474..59d68a8865 100644 --- a/lib/python/debian_support.py +++ b/lib/python/debian_support.py @@ -18,7 +18,7 @@ from __future__ import print_function """This module implements facilities to deal with Debian-specific metadata.""" -import gzip +import gzip, lzma import io import json import os.path @@ -28,8 +28,10 @@ import tempfile try: from urllib.request import urlopen + from urllib.error import URLError except ImportError: from urllib2 import urlopen + from urllib2.error import URLError try: from cStringIO import StringIO as streamIO @@ -111,10 +113,7 @@ class Version: return 'Version(%r)' % self.__asString def __cmp__(self, other): - try: - return apt_pkg.version_compare(self.__forCompare, other.__forCompare) - except AttributeError: - return apt_pkg.VersionCompare(self.__forCompare, other.__forCompare) + return apt_pkg.version_compare(self.__forCompare, other.__forCompare) def __lt__(self, other): return self.__cmp__(other) < 0 @@ -137,11 +136,8 @@ def version_compare(a, b): ~bpo and ~volatile suffixes are ignored.""" a = _version_normalize_regexp.sub("", a) b = _version_normalize_regexp.sub("", b) - try: - vc = apt_pkg.version_compare - except AttributeError: - vc = apt_pkg.VersionCompare - return vc(a, b) + + return apt_pkg.version_compare(a, b) class PackageFile: """A Debian package file. @@ -316,9 +312,6 @@ def patchLines(lines, patches): lines[first:last] = args def replaceFile(lines, local): - - import os.path - local_new = local + '.new' new_file = open(local_new, 'w+') @@ -331,32 +324,41 @@ def replaceFile(lines, local): if os.path.exists(local_new): os.unlink(local_new) -def downloadGunzipLines(remote): - """Downloads a file from a remote location and gunzips it. +def downloadCompressedLines(remote): + """Downloads a file from a remote location and uncompresses it. Returns the lines in the file.""" + if remote.endswith('.gz'): + cls = gzip + elif remote.endswith('.xz'): + cls = lzma + else: + raise ValueError('file format not supported: %s' % remote) + data = urlopen(remote, timeout=TIMEOUT) try: - gfile = gzip.GzipFile(fileobj=streamIO(data.read())) - try: - if sys.version_info.major == 3: - return io.TextIOWrapper(gfile).readlines() - else: - return gfile.readlines() - finally: - gfile.close() + b = io.BytesIO(cls.decompress(data.read())) + t = io.TextIOWrapper(b, 'utf-8') + return t.readlines() finally: data.close() - + +def downloadLines(remote): + try: + return downloadCompressedLines(remote + '.xz') + except URLError: + return downloadCompressedLines(remote + '.gz') + def downloadFile(remote, local): - """Copies a gzipped remote file to the local system. + """Copies a compressed remote file to the local system. - remote - URL, without the .gz suffix + remote - URL, without compression suffix local - name of the local file """ - - lines = downloadGunzipLines(remote + '.gz') + + lines = downloadLines(remote) + replaceFile(lines, local) return lines @@ -440,8 +442,10 @@ def updateFile(remote, local, verbose=None): if verbose: print("updateFile: downloading patch " + repr(patch_name)) try: - patch_contents = downloadGunzipLines(remote + '.diff/' + patch_name - + '.gz') + # We could remove the extension here and call downloadLines + # when diff files come with another compression + patch_contents = downloadCompressedLines(remote + '.diff/' + + patch_name + '.gz') except IOError: return downloadFile(remote, local) if readLinesSHA1(patch_contents ) != patch_hashes[patch_name]: @@ -573,6 +577,46 @@ def getconfig(): _config = json.load(open(findresource("data", "config.json"))) return _config +class PointUpdateParser: + @staticmethod + def parseNextPointUpdateStable(): + """ Reads data/next-point-update.txt and returns a dictionary such as: + + {'CVE-2014-10402': {'libdbi-perl': '1.642-1+deb10u2'}, + 'CVE-2019-10203': {'pdns': '4.1.6-3+deb10u1'} + } + """ + return PointUpdateParser._parsePointUpdateFile( + findresource("data", "next-point-update.txt") + ) + + @staticmethod + def parseNextOldstablePointUpdate(): + """ Returns a dictionary with the same structure as + PointUpdateParser.parseNextPointUpdateStable() for the file + data/next-oldstable-point-update.txt + """ + return PointUpdateParser._parsePointUpdateFile( + findresource("data", "next-oldstable-point-update.txt") + ) + + @staticmethod + def _parsePointUpdateFile(file_path): + CVE_RE = 'CVE-[0-9]{4}-[0-9X]{4,}' + result = {} + + with open(file_path) as f: + for line in f: + res = re.match(CVE_RE, line) + if res: + cve = res.group(0) + result[cve] = {} + continue + elif line.startswith('\t['): + dist, _, pkg, ver = line.split() + result[cve][pkg] = ver + return result + _releasecodename = None def releasecodename(dist): """Converts a release name to the code name. |