#!/bin/env python3
# SPDX-FileCopyrightText: OpenEmbedded Contributors
#
# SPDX-License-Identifier: MIT

# CVE results conversion script: JSON format to text
# Derived from cve-report.py from Oniro (MIT, by Huawei Inc)

import sys
import getopt

infile = "in.json"
outfile = "out.txt"


def show_syntax_and_exit(code):
    """
    Show the program syntax and exit with an errror
    Arguments:
        code: the error code to return
    """
    print("Syntax: %s [-h] [-i inputJSONfile][-o outputfile]" % sys.argv[0])
    sys.exit(code)


def exit_error(code, message):
    """
    Show the error message and exit with an errror
    Arguments:
        code: the error code to return
        message: the message to show
    """
    print("Error: %s" % message)
    sys.exit(code)


def parse_args(argv):
    """
    Parse the program arguments, put options in global variables
    Arguments:
        argv: program arguments
    """
    global infile, outfile
    try:
        opts, args = getopt.getopt(
            argv, "hi:o:", ["help", "input", "output"]
        )
    except getopt.GetoptError:
        show_syntax_and_exit(1)
    for opt, arg in opts:
        if opt in ("-h"):
            show_syntax_and_exit(0)
        elif opt in ("-i"):
            infile = arg
        elif opt in ("-o"):
            outfile = arg

def load_json(filename):
    """
    Load the JSON file, return the resulting dictionary
    Arguments:
        filename: the file to open
    Returns:
        Parsed file as a dictionary
    """
    import json

    out = {}
    try:
        with open(filename, "r") as f:
            out = json.load(f)
    except FileNotFoundError:
        exit_error(1, "Input file (%s) not found" % (filename))
    except json.decoder.JSONDecodeError as error:
        exit_error(1, "Malformed JSON file: %s" % str(error))
    return out


def process_data(filename, data):
    """
    Write the resulting CSV with one line for each package
    Arguments:
        filename: the file to write to
        data: dictionary from parsing the JSON file
    Returns:
        None
    """
    if not "version" in data or data["version"] != "1":
        exit_error(1, "Unrecognized format version number")
    if not "package" in data:
        exit_error(1, "Mandatory 'package' key not found")

    lines = ""
    total_issue_count = 0
    for package in data["package"]:
        package_info = ""
        keys_in_package = {"name", "layer", "version", "issue"}
        if keys_in_package - package.keys():
            exit_error(
                1,
                "Missing a mandatory key in package: %s"
                % (keys_in_package - package.keys()),
            )

        package_info += "LAYER: %s\n" % package["layer"]
        package_info += "PACKAGE NAME: %s\n" % package["name"]
        package_info += "PACKAGE VERSION: %s\n" % package["version"]

        for issue in package["issue"]:
            keys_in_issue = {"id", "status", "detail"}
            if keys_in_issue - issue.keys():
                print("Warning: Missing keys %s in 'issue' for the package '%s'"
                    % (keys_in_issue - issue.keys(), package["name"]))

            lines += package_info
            lines += "CVE: %s\n" % issue["id"]
            lines += "CVE STATUS: %s\n" % issue["status"]
            lines += "CVE DETAIL: %s\n" % issue["detail"]
            if "description" in issue:
                lines += "CVE DESCRIPTION: %s\n" % issue["description"]
            if "summary" in issue:
                lines += "CVE SUMMARY: %s\n" % issue["summary"]
            if "scorev2" in issue:
                lines += "CVSS v2 BASE SCORE: %s\n" % issue["scorev2"]
            if "scorev3" in issue:
                lines += "CVSS v3 BASE SCORE: %s\n" % issue["scorev3"]
            if "scorev4" in issue:
                lines += "CVSS v4 BASE SCORE: %s\n" % issue["scorev4"]
            if "vector" in issue:
                lines += "VECTOR: %s\n" % issue["vector"]
            if "vectorString" in issue:
                lines += "VECTORSTRING: %s\n" % issue["vectorString"]
            lines += "MORE INFORMATION: https://nvd.nist.gov/vuln/detail/%s\n" % issue["id"]
            lines += "\n"

    with open(filename, "w") as f:
        f.write(lines)

def main(argv):
    parse_args(argv)
    data = load_json(infile)
    process_data(outfile, data)


if __name__ == "__main__":
    main(sys.argv[1:])
