diff options
author | Bjoern Tropf <asymmail@googlemail.com> | 2009-07-23 20:42:52 +0200 |
---|---|---|
committer | Bjoern Tropf <asymmail@googlemail.com> | 2009-07-23 20:42:52 +0200 |
commit | 01c57949e986f590a80a8146bcfb517855a23845 (patch) | |
tree | ab47505dd5785c57245fb76412ad7335c35a4f4d | |
parent | Backup commit (diff) | |
download | kernel-check-01c57949e986f590a80a8146bcfb517855a23845.tar.gz kernel-check-01c57949e986f590a80a8146bcfb517855a23845.tar.bz2 kernel-check-01c57949e986f590a80a8146bcfb517855a23845.zip |
Change max line length to 79
Start work on documentation
Fix some minor bugs
Edit the TODO list
-rw-r--r-- | TODO | 54 | ||||
-rwxr-xr-x | collector.py | 17 | ||||
-rwxr-xr-x | kernel-check.py | 23 | ||||
-rwxr-xr-x | kernellib.py | 261 |
4 files changed, 203 insertions, 152 deletions
@@ -1,52 +1,16 @@ Todo ==== -- Fix all TODO markers +- Fix all inline TODO/FIXME markers - Find a solution for <ref source url/> -- Rename functions +- Use telling function- and variable names - Rework interval class and all interval functions (expand?) - Rework cves.refs -- class(object) (new class) - Use exeptions instead of debug() -- Break lines - -Clean code -========== -- Use telling variables -- Use proper Descriptions -- Remove unused code / find better ways -- Add error handling - -Documentation -============= +- Add further error handling +- [kernel +<version] -> [+kernel <version] +- Ignore vserver whiteboard +- Find a way to insert arch into bugzilla +- Implement find_cve() (return bugid) +- Write a proper documentation - Implement DTD -- Function documentation / manpages - -Intervall documentation -======================= - -name: String, the name of the vulnerable release. This can either be "linux" to - specify the upstream release was vulnerable, "genpatches" (or abbreviated "gp") - or a specifc ebuild name such as "hppa-sources" (or abbreviated "hppa"). - -lower: String, the lower boundary. - -upper: String, the upper boundary. - -lower_inclusive: Boolean, whether or not the lower boundary is inclusive. - -upper_inclusive: Boolean, whether or not the upper boundary is inclusive. - -expand: Boolean, defines whether the entry is shadowing less specific entries of the same version range: - linux is less specific than genpatches which is less specific than the name. - Example: - (1) [linux >= 2.6.18 < 2.6.24.3] [gp+ >2.6.16-1 < 2.6.23-8] - (expand=True) - - (2) [linux >= 2.6.18 < 2.6.24.3] [gp < 2.6.23-8] - (expand=False) - - In (1), a vulnerability seemingly has been backported to genpatches-2.1.16-1 - and was fixed in 2.6.23-8. A genpatched Kernel 2.6.17 is vulnerable. In (2), - a patch fixing the vulnerability has been backported to the genpatches. - Kernels 2.6.17 and earlier are not affected. - +- Remove unused code and find better ways diff --git a/collector.py b/collector.py index 045d9ed..0b41479 100755 --- a/collector.py +++ b/collector.py @@ -7,6 +7,7 @@ import getopt import os import sys import time + import kernellib as lib @@ -30,9 +31,9 @@ def main(argv): elif opt in ('-s', '--skip'): lib.SKIP = True elif opt in ('-t', '--tree'): - if os.access(os.path.dirname(arg) , os.W_OK): - if os.path.isdir(arg): - lib.TREE = arg + if os.access(os.path.dirname(arg) , os.W_OK) and \ + os.path.isdir(arg): + lib.TREE = arg elif opt in ('-v', '--verbose'): lib.VERBOSE = True @@ -88,17 +89,21 @@ def main(argv): time.sleep(lib.DELAY) except lib.InvalidWhiteboardError, e: - print '\n[%s] Invalid Whiteboard' % item + print '\n[%s] Invalid whiteboard' % item print '%s' % e.value except lib.InvalidCveError, e: - print '\n[%s] Invalid Cve' % item + print '\n[%s] Invalid CVE' % item print '%s' % e.value except lib.NvdEntryError, e: #print '\n[%s] No Nvd Entry' % item #print '%s' % e.value - pass + created_files += 1 + + except lib.CveDuplicateError, e: + print '\n[%s] CVE Duplicate' % item + print '%s' % e.value print '\nCreated %i xml files!' % created_files diff --git a/kernel-check.py b/kernel-check.py index c071dc1..970c49b 100755 --- a/kernel-check.py +++ b/kernel-check.py @@ -7,12 +7,12 @@ import getopt import portage import sys import os + import kernellib as lib def main(argv): 'Main function' - #FIXME info = portage.output.EOutput().einfo warn = portage.output.EOutput().ewarn error = portage.output.EOutput().eerror @@ -44,7 +44,8 @@ def main(argv): kernel = lib.extract_version(os.uname()[2]) best = lib.best_version(kernel.source) if kernel is not None: - info('Kernel version: %s' % (color('GOOD', '%s-%s' % (kernel.version, kernel.revision)))) + info('Kernel version: %s' % (color('GOOD', '%s-%s' % + (kernel.version, kernel.revision)))) info('Kernel sources: %s' % color('GOOD', kernel.source)) else: error('No kernel information found!') @@ -52,7 +53,8 @@ def main(argv): genpatch = lib.get_genpatch(lib.read_genpatch_file('out'), kernel) if genpatch is not None: - info('Integrated genpatch: %s' % color('GOOD', '%s %s' % (genpatch.version, repr(genpatch)))) + info('Integrated genpatch: %s' % color('GOOD', '%s %s' % + (genpatch.version, repr(genpatch)))) else: warn('No genpatch information found!') @@ -73,12 +75,14 @@ def main(argv): info('%s have been fixed' % color('GOOD', str(schedule.fixed))) if len(schedule.canfix): - error('%s can be fixed by upgrading' % color('BAD', str(len(schedule.canfix)))) + error('%s can be fixed by upgrading' % + color('BAD', str(len(schedule.canfix)))) else: info('No vulnerability can be fixed by upgrading') if len(schedule.notfix): - warn('%s have not been fixed yet' % color('WARN', str(len(schedule.notfix)))) + warn('%s have not been fixed yet' % + color('WARN', str(len(schedule.notfix)))) else: info('No vulnerability have not been fixed yet') @@ -91,16 +95,17 @@ def main(argv): for item in schedule.canfix: print '\n Bugid %s:' % item.bugid for cve in item.cves: - print ' %s - %s\n "%s..."' % (cve.cve, cve.severity, cve.desc[:term[1]-14]) + print ' %s - %s\n "%s..."' % (cve.cve, + cve.severity, cve.desc[:term[1]-14]) print '' info('To print more information about a vulnerability try:') info(' $ %s -i [bugid]' % sys.argv[0]) info('') - info('It is recommended to upgrade your kernel to [%s]' % color('GOOD', best)) + info('It is recommended to upgrade your kernel to [%s]' % + color('GOOD', best)) else: info('') - info('Your kernel is not affected by any known') #FIXME - info('and fixed vulnerabilities!') + info('Your kernel is up to date!') def usage(): diff --git a/kernellib.py b/kernellib.py index 51d882e..297a93e 100755 --- a/kernellib.py +++ b/kernellib.py @@ -15,23 +15,28 @@ import portage import re import urllib -ARCHES = ['all', 'alpha', 'amd64', 'amd64-fbsd', 'arm', 'hppa', 'ia64', 'm68k', 'mips', - 'ppc', 'ppc64', 's390', 'sh', 'sparc', 'sparc-fbsd', 'x86', 'x86-fbsd'] +ARCHES = ['all', 'alpha', 'amd64', 'amd64-fbsd', 'arm', 'hppa', 'ia64', 'm68k', + 'mips', 'ppc', 'ppc64', 's390', 'sh', 'sparc', 'sparc-fbsd', 'x86', + 'x86-fbsd'] BUGORDER = ['bugid', 'reporter', 'reported', 'status', 'arch', 'affected'] CVEORDER = ['cve', 'published', 'desc', 'severity', 'vector', 'score', 'refs'] +#TODO Check lookaround of 'grpall' REGEX = { 'bugzilla' : re.compile(r'(?<=bug.cgi\?id=)\d*'), 'gpatches_v' : re.compile(r'(?<=K_GENPATCHES_VER\=\").+(?=\")'), 'gpatches_w' : re.compile(r'(?<=K_WANT_GENPATCHES\=\").+(?=\")'), - 'groupall' : re.compile(r'[ (]*CVE-(\d{4})([-,(){}|, \d]+)'), - 'groupsplit' : re.compile(r'(?<=\D)(\d{4})(?=\D|$)'), + 'grpall' : re.compile(r'(?<=\()[ (]*CVE-(\d{4})([-,(){}|, \d]+)(?=\))'), + 'grpsplit' : re.compile(r'(?<=\D)(\d{4})(?=\D|$)'), 'nomatch' : re.compile(r'.*GENERIC-MAP-NOMATCH.*'), - 'wb_match' : re.compile(r'\s*\[\s*([^ +<=>]+)\s*(\+?)\s*([<=>]{1,2})\s*([^ <=>\]]+)\s*(?:([<=>]{1,2})\s*([^ \]]+))?\s*\]\s*(.*)'), #FIXME - 'wb_version' : re.compile(r'^(?:\d{1,2}\.){0,3}\d{1,2}(?:[-_](?:r|rc)?\d{1,2})*$'), + 'wb_match' : re.compile(r'\s*\[\s*([^ +<=>]+)\s*(\+?)\s*([<=>]{1,2})\s' \ + r'*([^ <=>\]]+)\s*(?:([<=>]{1,2})\s*([^ \]]+))' \ + r'?\s*\]\s*(.*)'), + 'wb_version' : re.compile(r'^(?:\d{1,2}\.){0,3}\d{1,2}(?:[-_](?:r|rc)?\d' \ + r'{1,2})*$'), 'version' : re.compile(r'^((?:\d{1,2}\.){0,4}\d{1,2})(-.*)?$'), 'rcd' : re.compile(r'^rc\d{1,3}$'), @@ -39,19 +44,27 @@ REGEX = { 'rd' : re.compile(r'^r\d{1,3}$') } -GENERAL_KERNEL_TYPES = ['aa', 'acpi', 'ac', 'alpha', 'arm', 'as', 'cell', 'ck', 'compaq', 'crypto', - 'development', 'gaming','gentoo-dev', 'gentoo', 'gentoo-test', 'gfs', 'git', 'grsec', 'gs', - 'hardened-dev', 'hardened', 'hppa-dev', 'hppa', 'ia64', 'kurobox', 'linux', 'lolo', - 'mips-prepatch', 'mips', 'mjc', 'mm', 'mosix', 'openblocks', 'openmosix','openvz', 'pac', - 'pegasos-dev', 'pegasos', 'pfeifer', 'planet-ccrma', 'ppc64', 'ppc-development', 'ppc-dev', - 'ppc', 'redhat', 'rsbac-dev', 'rsbac', 'selinux', 'sh', 'sparc-dev', 'sparc', 'suspend2', - 'systrace', 'tuxonice', 'uclinux', 'usermode','vanilla-prepatch', 'vanilla', 'vanilla-tiny', - 'vserver-dev', 'vserver', 'win4lin', 'wolk-dev', 'wolk', 'xbox', 'xen', 'xfs'] - -GENTOO_KERNEL_TYPES = ['cell', 'mips', 'tuxonice', 'mm', 'usermode', 'gentoo', 'vanilla', 'git', - 'openvz', 'vserver', 'hardened', 'sh', 'xbox', 'sparc', 'xen'] - -VERSION = '0.5.2' +GENERAL_KERNEL = ['aa', 'acpi', 'ac', 'alpha', 'arm', 'as', 'cell', 'ck', + 'compaq', 'crypto', 'development', 'gaming','gentoo-dev', + 'gentoo', 'gentoo-test', 'gfs', 'git', 'grsec', 'gs', + 'hardened-dev', 'hardened', 'hppa-dev', 'hppa', 'ia64', + 'kurobox', 'linux', 'lolo', 'mips-prepatch', 'mips', 'mjc', + 'mm', 'mosix', 'openblocks', 'openmosix','openvz', 'pac', + 'pegasos-dev', 'pegasos', 'pfeifer', 'planet-ccrma', 'ppc64', + 'ppc-development', 'ppc-dev', 'ppc', 'redhat', 'rsbac-dev', + 'rsbac', 'selinux', 'sh', 'sparc-dev', 'sparc', 'suspend2', + 'systrace', 'tuxonice', 'uclinux', 'usermode', + 'vanilla-prepatch', 'vanilla', 'vanilla-tiny', 'vserver-dev', + 'vserver', 'win4lin', 'wolk-dev', 'wolk', 'xbox', 'xen', + 'xfs'] + +GENTOO_KERNEL = ['cell', 'mips', 'tuxonice', 'mm', 'usermode', 'gentoo', + 'vanilla', 'git', 'openvz', 'vserver', 'hardened', 'sh', + 'xbox', 'sparc', 'xen'] + +VERSION = '0.5.3' +NOCVE = 'GENERIC-MAP-NOMATCH' +CVES = dict() VERBOSE = False FORCE = False SKIP = False @@ -65,7 +78,8 @@ FOLDER = { } #TODO Deprecated -logging.basicConfig(format='%(levelname)-6s[%(asctime)s] : %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) +logging.basicConfig(format='%(levelname)-6s[%(asctime)s] : %(message)s', + datefmt='%H:%M:%S', level=logging.DEBUG) #TODO Deprecated def debug(msg): @@ -77,49 +91,63 @@ class InvalidWhiteboardError(Exception): def __init__(self, value): self.value = value - def __str__(self): - return repr(self.value) - - class InvalidCveError(Exception): def __init__(self, value): self.value = value - def __str__(self): - return repr(self.value) - +class CveDuplicateError(Exception): + def __init__(self, value): + self.value = value class NvdEntryError(Exception): def __init__(self, value): self.value = value - def __str__(self): - return repr(self.value) - - class Schedule: - 'Schedule class' - - read = int() - match = int() - fixed = int() + """Schedule class + + Provides information about the vulnerability of the current system. + There is only one instance of this class available. + + Attributes: + read: an integer count represeting the number of read files. + match: an integer count of bugs matching this system architecture. + fixed: an integer count of bugs being fixed in the current kernel. + canfix: a list of bugs that could be fixed by upgrading the kernel. + notfix: a list representing unresolved bugs in gentoo bugzilla. + """ + + read = int() + match = int() + fixed = int() canfix = list() notfix = list() def __init__(self, read): self.read = read - class Cve: - 'Cve class' - - cve = str() - desc = str() + """Common vulnerabilities and exposures class + + Contains all important information about a cve. + + Attributes: + cve: a string represeting the cve number of the class. + desc: a string providing a detailed description for the cve. + published: a string representing the original cve release date. + refs: a list of external references. + severity: a string representing the cve severity. + score: a floating point representing cvss base score. + vector: a string providing the cve access vector. + """ + + cve = str() + desc = str() published = str() - refs = list() - severity = str() - score = float() - vector = str() + refs = list() + severity = str() + score = float() + vector = str() def __init__(self, cve): self.cve = cve @@ -162,8 +190,8 @@ class Kernel: 'Kernel class' revision = str() - source = str() - version = str() + source = str() + version = str() def __init__(self, source): self.source = source @@ -199,7 +227,18 @@ class Vulnerability: class Interval: - 'Interval class' + """Interval class + + Provides one interval entry for a vulnerability + + Attributes: + name: a string representing the name of the kernel release + lower: a string representing the lower boundary of the interval + upper: a string representing the upper boundary of the interval + lower_i: a boolean indicating if the lower boundary is inclusive + upper_i: a boolean indicating if the upper boundary is inclusive + expand: a boolean indicating if the interval is shadowing other intervals + """ name = str() lower = str() @@ -295,7 +334,7 @@ def interval_from_xml(root): #TODO short function #TODO Use exceptions def is_in_interval(interval, version): - 'Returns True if the given version is inside our specified interval, False otherwise' + 'Returns True if the given version is inside our specified interval' #TODO: raise exception if version == None: @@ -328,6 +367,31 @@ def is_in_interval(interval, version): return True +def extract_genpatch(ebuild, directory, sources): + 'Returns a genpatch from an ebuild' + + pkg = portage.versions.catpkgsplit('sys-kernel/%s' % ebuild[:-7]) + + with open(os.path.join(directory, sources, ebuild), 'r') as ebuild_file: + content = ebuild_file.read() + + try: + genpatch_v = REGEX['gpatches_v'].findall(content)[0] + genpatch_w = REGEX['gpatches_w'].findall(content)[0] + except: + return None + + kernel = Kernel(pkg[1]) + kernel.version = pkg[2] + kernel.revision = pkg[3] + + genpatch = Genpatch(pkg[2] + '-' + genpatch_v) + genpatch.kernel = kernel + genpatch.base = ('base' in genpatch_w) + genpatch.extras = ('extras' in genpatch_w) + + return genpatch + def parse_genpatch_list(directory): 'Returns a list containing all genpatches from portage' @@ -339,27 +403,9 @@ def parse_genpatch_list(directory): if '-sources' in sources: for ebuild in os.listdir(os.path.join(directory, sources)): if '.ebuild' in ebuild: + genpatch = extract_genpatch(ebuild, directory, sources) - pkg = portage.versions.catpkgsplit('sys-kernel/%s' % ebuild[:-7]) - - with open(os.path.join(directory, sources, ebuild), 'r') as ebuild_file: - content = ebuild_file.read() - - try: - genpatch_v = REGEX['gpatches_v'].findall(content)[0] - genpatch_w = REGEX['gpatches_w'].findall(content)[0] - except: - break - - kernel = Kernel(pkg[1]) - kernel.version = pkg[2] - kernel.revision = pkg[3] - - genpatch = Genpatch(pkg[2] + '-' + genpatch_v) - genpatch.kernel = kernel - genpatch.base = ('base' in genpatch_w) - genpatch.extras = ('extras' in genpatch_w) - + if genpatch is not None: patches.append(genpatch) return patches @@ -429,7 +475,7 @@ def parse_bugzilla_list(directory): def parse_bugzilla_dict(directory, bugid): - 'Returns a vulnerability class containing information about a bugzilla bug' + 'Returns a vulnerability class containing information about a bug' filename = os.path.join(directory, bugid) @@ -444,7 +490,12 @@ def parse_bugzilla_dict(directory, bugid): if not vul.cvelist: raise InvalidCveError(root.find('short_desc').text) - vul.affected = from_whiteboard(root.find('status_whiteboard').text) + for item in vul.cvelist: + if item != NOCVE: + if item not in CVES: + CVES[item] = vul.bugid + else: + raise CveDuplicateError(CVES[item]) vul.arch = root.find('rep_platform').text.lower() vul.reported = root.find('creation_ts').text @@ -452,8 +503,14 @@ def parse_bugzilla_dict(directory, bugid): vul.status = root.find('bug_status').text.lower() except AttributeError: - pass #TODO Error + pass + + try: + vul.affected = from_whiteboard(root.find('status_whiteboard').text) + + except AttributeError: + raise InvalidWhiteboardError('Empty') return vul @@ -463,6 +520,10 @@ def search_nvd_dict(nvd, vul): cves = list() for item in vul.cvelist: + if item == NOCVE: + vul.cves = list() + return vul + try: cves.append(nvd[item]) except KeyError: @@ -474,7 +535,7 @@ def search_nvd_dict(nvd, vul): def parse_nvd_dict(directory): - 'Returns a dictionary containing all CVEs from the National Vulnerability Database' + 'Returns a dictionary from the National Vulnerability Database' nvd = dict() @@ -494,7 +555,8 @@ def parse_nvd_dict(directory): cve.vector = tree.get('CVSS_vector') cve.score = tree.get('CVSS_score') - desc = tree.find('%sdesc/%sdescript/' % (namespace, namespace)) #FIXME + #FIXME + desc = tree.find('%sdesc/%sdescript/' % (namespace, namespace)) if desc is not None: cve.desc = desc.text @@ -505,7 +567,8 @@ def parse_nvd_dict(directory): elem.tag = elem.tag.replace(namespace, '') bugref = et.SubElement(reftree, 'ref') bugref.set('source', 'GENTOO') - bugref.set('url', 'https://bugs.gentoo.org/show_bug.cgi?id=%s' % cve.cve) + bugref.set('url', 'https://bugs.gentoo.org/show_bug.cgi?id=%s' % + cve.cve) bugref.text = 'Gentoo %s' % cve.cve cve.refs = reftree @@ -540,10 +603,10 @@ def extract_cves(string): string = string.replace('CAN', 'CVE') if string in REGEX['nomatch'].findall(string): - return ['GENERIC-MAP-NOMATCH'] + return [NOCVE] - for (year, split_cves) in REGEX['groupall'].findall(string): - for cve in REGEX['groupsplit'].findall(split_cves): + for (year, split_cves) in REGEX['grpall'].findall(string): + for cve in REGEX['grpsplit'].findall(split_cves): cves.append('CVE-%s-%s' % (year, cve)) return cves @@ -564,7 +627,8 @@ def parse_cve_files(directory, kernel, best, arch): for item in files: if item.arch not in ARCHES: - debug('[Error] Wrong architecture %s in bugid: %s' % (item.arch, item.bugid)) + debug('[Error] Wrong architecture %s in bugid: %s' % + (item.arch, item.bugid)) if item.arch == arch or item.arch == 'all': schedule.match += 1 @@ -668,7 +732,7 @@ def from_whiteboard(whiteboard): 'Returns a list of intervals within a whiteboard string' if whiteboard == None: - raise InvalidWhiteboardError(whiteboard) + print 'whiteboard == None called' #FIXME does this happen? wb = { 'expand' : False, @@ -725,7 +789,9 @@ def from_whiteboard(whiteboard): if version and not REGEX['wb_version'].match(version): raise InvalidWhiteboardError(whiteboard) - affected.append(Interval(name, wb['lower'], wb['upper'], wb['lower_inc'], wb['upper_inc'], wb['expand'])) + affected.append(Interval(name, wb['lower'], wb['upper'], + wb['lower_inc'], wb['upper_inc'], + wb['expand'])) whiteboard = match.group(7) return affected @@ -736,7 +802,8 @@ def extract_version(release): match = REGEX['version'].match(release) if not match: - debug('[Error] Release %s does not contain any valid kernel information' % release) + debug('[Error] Release %s does not contain any valid information' % + release) return None version, rest = match.groups() @@ -755,13 +822,14 @@ def extract_version(release): kernel.revision = 'r' + REGEX['gitd'].match(elem).groups()[0] elif REGEX['rd'].match(elem): kernel.revision = elem - elif elem in GENERAL_KERNEL_TYPES: - if elem in GENTOO_KERNEL_TYPES: + elif elem in GENERAL_KERNEL: + if elem in GENTOO_KERNEL: kernel.source = elem + '-sources' else: kernel.source = elem elif elem != '': - debug('[Error] Dropping unknown version component \'%s\', probably local tag.' % elem) + debug('[Error] Dropping unknown version component \'%s\', \ + probably local tag.' % elem) return kernel @@ -776,16 +844,20 @@ def best_version(source): return best[11:] -def receive_file(directory, path, xml_file, max_age = datetime.timedelta(0, 59*60)): +def receive_file(directory, path, xml_file, + max_age = datetime.timedelta(0, 59*60)): 'Generic download function' filename = os.path.join(directory, xml_file) if not FORCE: if os.path.exists(filename): - age = datetime.datetime.now() - datetime.datetime.fromtimestamp(os.path.getmtime(filename)) + age = datetime.datetime.now() - \ + datetime.datetime.fromtimestamp(os.path.getmtime(filename)) if age < max_age: - debug('File %s - %sKB is recent enough [%s]' % (filename, os.path.getsize(filename)/1024, str(age)[:-7])) + debug('File %s - %sKB is recent enough [%s]' % + (filename, os.path.getsize(filename)/1024, + str(age)[:-7])) return with closing(cStringIO.StringIO()) as data: @@ -795,7 +867,8 @@ def receive_file(directory, path, xml_file, max_age = datetime.timedelta(0, 59*6 with open(filename, 'w') as output: output.write(data.getvalue()) - debug('File %s - %sKB received' % (filename, os.path.getsize(filename)/1024)) + debug('File %s - %sKB received' % + (filename, os.path.getsize(filename)/1024)) def receive_nvd_recent(directory): @@ -816,16 +889,20 @@ def receive_nvd_all(directory): year = 2020 for i in xrange(2002, year + 1): - receive_file(directory, path, 'nvdcve-' + str(i) + '.xml', max_age = datetime.timedelta(1)) + receive_file(directory, path, 'nvdcve-' + str(i) + '.xml', + max_age = datetime.timedelta(1)) def receive_bugzilla_list(directory): 'Download a list containing all Bugzilla kernel bugs' status = ['NEW', 'ASSIGNED', 'REOPENED', 'RESOLVED', 'VERIFIED', 'CLOSED'] - resolution = ['FIXED', 'LATER', 'CANTFIX', 'TEST-REQUEST', 'UPSTREAM', '---'] + resolution = ['FIXED', 'LATER', 'CANTFIX', 'TEST-REQUEST', 'UPSTREAM', + '---'] #FIXME Remove CANTFIX ? + + path = ['https://bugs.gentoo.org/buglist.cgi?', + 'query_format=advanced&component=Kernel'] - path = ['https://bugs.gentoo.org/buglist.cgi?query_format=advanced&component=Kernel'] for i in status: path.append('&bug_status=' + i) for i in resolution: |