#!/usr/bin/env python2

# Author: Jamie Strandboge <jamie@ubuntu.com>
# Copyright (C) 2005-2017 Canonical Ltd.
#
# This script is distributed under the terms and conditions of the GNU General
# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html
# for details.

import sys
import optparse
import cve_lib

import source_map

packages = dict()
assignees = dict()
pkg_assignees = dict()
popularity = dict()
pockets = {'esm': dict(),
           'ppa': dict(),
           'archive': dict()}

parser = optparse.OptionParser()
parser.add_option("-S", "--skip-devel", help="Show only those CVEs *not* in the current devel release", action="store_true")
parser.add_option("-D", "--only-devel", help="Show only those CVEs in the current devel release", action="store_true")
parser.add_option("-e", "--only-esm", help="Show only packages updated by the esm team", action="store_true")
parser.add_option("-x", "--not-esm", help="Show only those packages not updated by the esm team", action="store_true")
parser.add_option("-p", "--packages", help="Report only on the given packages", action="append", type="string")
parser.add_option("-P", "--pkgfamily", help="Perform pkg family renamings (use argument multiple times for 'linux' and/or 'xen')", action="append", default=[])
parser.add_option("-X", "--exclude", help="Ignore specified packages", action="append", type="string")
parser.add_option("-r", "--release", help="Report only for the given releases", action="append", type="string")
parser.add_option("-d", "--debug", help="Report debug information while loading", action="store_true")
(opt, args) = parser.parse_args()

releases = cve_lib.all_releases
for eol in cve_lib.eol_releases:
    if eol in releases:
        releases.remove(eol)

if opt.skip_devel and cve_lib.devel_release != '':
    releases.remove(cve_lib.devel_release)

if opt.only_devel:
    releases = [cve_lib.devel_release]

if opt.release:
    releases = opt.release
    srcmap = source_map.load(releases=releases, skip_eol_releases=False)
else:
    srcmap = source_map.load()


(cves, uems, rcves) = cve_lib.get_cve_list_and_retired()
table = cve_lib.load_all(cves, uems, rcves)

for cve in sorted(cves):
    if cve not in table:
        continue

    for pkg in sorted(table[cve]['pkgs'].keys()):
        if opt.exclude and pkg in opt.exclude:
            continue

        found = False
        esm = False
        ppa = False
        archive = False
        version = 0
        for r in releases:
            status = table[cve]['pkgs'][pkg]
            if r in status:
                if status[r][0].startswith('released'):
                    #print >>sys.stderr, "%s for %s in %s (%s)" % (cve, pkg, r, table[cve][pkg][r])
                    found = True
                    version = status[r][1]

                    if 'esm' in status[r][1]:
                        esm = True
                        ppa = True
                    elif r == 'trusty/esm':
                        if status[r][0].startswith('released-'):
                            # workaround for trusty/esm as its source_map
                            # is different from other esms
                            esm = True
                            archive = True
                    elif cve_lib.is_universe(srcmap, pkg, r, None):
                        if 'ubuntu' in version or 'build' in version:
                            esm = True
                            archive = True

        if not found:
            continue

        if opt.only_esm and not esm:
            continue

        if opt.not_esm and esm:
            continue

        if esm:
            if pkg in pockets['esm']:
                pockets['esm'][pkg] += 1
            else:
                pockets['esm'][pkg] = 1
        if ppa:
            if pkg in pockets['ppa']:
                pockets['ppa'][pkg] += 1
            else:
                pockets['ppa'][pkg] = 1
        if archive:
            if pkg in pockets['archive']:
                pockets['archive'][pkg] += 1
            else:
                pockets['archive'][pkg] = 1


        if pkg in packages:
            packages[pkg]['cves'] += 1
            if version not in packages[pkg]['version']:
                packages[pkg]['version'].append(version)
        else:
            packages[pkg] = {}
            packages[pkg]['cves'] = 1
            packages[pkg]['version'] = [version]


sys.stdout.write("Updates\tCVEs Fixed\tPackage\n")
sys.stdout.write("---------------------------------------------------------------------\n")

for pkg in sorted(packages.keys()):
    sys.stdout.write("%s\t%s\t\t%s" % (str(len(packages[pkg]['version'])), str(packages[pkg]['cves']), pkg))

    extra_info = []
    for p in pockets.keys():
        if pkg in pockets[p]:
            extra_info.append(p.upper())

    if len(extra_info) > 0:
        sys.stdout.write(" (%s)" % ",".join(extra_info))

    sys.stdout.write("\n")
