#!/usr/bin/env python

# Copyright (C) 2009 by Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
# Copyright (C) 2020 by Gregory CLEMENT <gregory.clement@bootlin.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import argparse
import datetime
import os
import json
import sys
import cve as cvecheck


class Package:
    def __init__(self, name, version, ignored_cves):
        self.name = name
        self.version = version
        self.cves = list()
        self.ignored_cves = ignored_cves


def check_package_cves(nvd_path, packages):
    if not os.path.isdir(nvd_path):
        os.makedirs(nvd_path)

    for cve in cvecheck.CVE.read_nvd_dir(nvd_path):
        for pkg_name in cve.pkg_names:
            pkg = packages.get(pkg_name, '')
            if pkg and cve.affects(pkg.name, pkg.version, pkg.ignored_cves) == cve.CVE_AFFECTS:
                pkg.cves.append(cve.identifier)


html_header = """
<head>
<script src=\"https://www.kryogenix.org/code/browser/sorttable/sorttable.js\"></script>
<style type=\"text/css\">
table {
  width: 100%;
}
td {
  border: 1px solid black;
}
td.centered {
  text-align: center;
}
td.wrong {
  background: #ff9a69;
}
td.correct {
  background: #d2ffc4;
}

</style>
<title>CVE status for Buildroot configuration</title>
</head>

<p id=\"sortable_hint\"></p>
"""


html_footer = """
</body>
<script>
if (typeof sorttable === \"object\") {
  document.getElementById(\"sortable_hint\").innerHTML =
  \"hint: the table can be sorted by clicking the column headers\"
}
</script>
</html>
"""


def dump_html_pkg(f, pkg):
    f.write(" <tr>\n")
    f.write("  <td>%s</td>\n" % pkg.name)

    # Current version
    if len(pkg.version) > 20:
        version = pkg.version[:20] + "..."
    else:
        version = pkg.version
    f.write("  <td class=\"centered\">%s</td>\n" % version)

    # CVEs
    td_class = ["centered"]
    if len(pkg.cves) == 0:
        td_class.append("correct")
    else:
        td_class.append("wrong")
    f.write("  <td class=\"%s\">\n" % " ".join(td_class))
    for cve in pkg.cves:
        f.write("   <a href=\"https://security-tracker.debian.org/tracker/%s\">%s<br/>\n" % (cve, cve))
    f.write("  </td>\n")

    f.write(" </tr>\n")


def dump_html_all_pkgs(f, packages):
    f.write("""
<table class=\"sortable\">
<tr>
<td>Package</td>
<td class=\"centered\">Version</td>
<td class=\"centered\">CVEs</td>
</tr>
""")
    for pkg in packages:
        dump_html_pkg(f, pkg)
    f.write("</table>")


def dump_html_gen_info(f, date):
    f.write("<p><i>Generated on %s</i></p>\n" % (str(date)))


def dump_html(packages, date, output):
    with open(output, 'w') as f:
        f.write(html_header)
        dump_html_all_pkgs(f, packages)
        dump_html_gen_info(f, date)
        f.write(html_footer)


def dump_json(packages, date, output):
    # Format packages as a dictionnary instead of a list
    pkgs = {
        pkg.name: {
            "version": pkg.version,
            "cves": pkg.cves,
        } for pkg in packages
    }
    # The actual structure to dump, add date to it
    final = {'packages': pkgs,
             'date': str(date)}
    with open(output, 'w') as f:
        json.dump(final, f, indent=2, separators=(',', ': '))
        f.write('\n')


def resolvepath(path):
        return os.path.abspath(os.path.expanduser(path))


def parse_args():
    parser = argparse.ArgumentParser()
    output = parser.add_argument_group('output', 'Output file(s)')
    output.add_argument('--html', dest='html', type=resolvepath,
                        help='HTML output file')
    output.add_argument('--json', dest='json', type=resolvepath,
                        help='JSON output file')
    parser.add_argument('--nvd-path', dest='nvd_path',
                        help='Path to the local NVD database', type=resolvepath,
                        required=True)
    args = parser.parse_args()
    if not args.html and not args.json:
        parser.error('at least one of --html or --json (or both) is required')
    return args


def __main__():
    packages = list()
    content = json.load(sys.stdin)
    for item in content:
        pkg = content[item]
        p = Package(item, pkg.get('version', ''), pkg.get('ignore_cves', ''))
        packages.append(p)

    args = parse_args()
    date = datetime.datetime.utcnow()

    print("Checking packages CVEs")
    check_package_cves(args.nvd_path, {p.name: p for p in packages})

    if args.html:
        print("Write HTML")
        dump_html(packages, date, args.html)
    if args.json:
        print("Write JSON")
        dump_json(packages, date, args.json)


__main__()
