|
@@ -718,89 +718,113 @@ def calculate_stats(packages):
|
|
|
|
|
|
|
|
|
|
html_header = """
|
|
html_header = """
|
|
|
|
+<!DOCTYPE html>
|
|
|
|
+<html lang="en">
|
|
<head>
|
|
<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;
|
|
|
|
-}
|
|
|
|
-td.nopatches {
|
|
|
|
- background: #d2ffc4;
|
|
|
|
-}
|
|
|
|
-td.somepatches {
|
|
|
|
- background: #ffd870;
|
|
|
|
-}
|
|
|
|
-td.lotsofpatches {
|
|
|
|
- background: #ff9a69;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-td.good_url {
|
|
|
|
- background: #d2ffc4;
|
|
|
|
-}
|
|
|
|
-td.missing_url {
|
|
|
|
- background: #ffd870;
|
|
|
|
-}
|
|
|
|
-td.invalid_url {
|
|
|
|
- background: #ff9a69;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-td.version-good {
|
|
|
|
- background: #d2ffc4;
|
|
|
|
-}
|
|
|
|
-td.version-needs-update {
|
|
|
|
- background: #ff9a69;
|
|
|
|
-}
|
|
|
|
-td.version-unknown {
|
|
|
|
- background: #ffd870;
|
|
|
|
-}
|
|
|
|
-td.version-error {
|
|
|
|
- background: #ccc;
|
|
|
|
|
|
+<meta charset="UTF-8">
|
|
|
|
+<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
+<script>
|
|
|
|
+function sortGrid(sortLabel){
|
|
|
|
+ let pkgSortArray = [], sortedPkgArray = [], pkgStringSortArray = [], pkgNumSortArray = [];
|
|
|
|
+ let columnValues = Array.from(document.getElementsByClassName(sortLabel));
|
|
|
|
+
|
|
|
|
+ columnValues.shift();
|
|
|
|
+ columnValues.forEach((listing) => {
|
|
|
|
+ let sortArr = [];
|
|
|
|
+ sortArr[0] = listing.id.replace(sortLabel+"_", "");
|
|
|
|
+ if (!listing.innerText){
|
|
|
|
+ sortArr[1] = -1;
|
|
|
|
+ } else {
|
|
|
|
+ sortArr[1] = listing.innerText;
|
|
|
|
+ };
|
|
|
|
+ pkgSortArray.push(sortArr);
|
|
|
|
+ })
|
|
|
|
+ pkgSortArray.forEach((listing) => {
|
|
|
|
+ if ( isNaN(parseInt(listing[1], 10)) ){
|
|
|
|
+ pkgStringSortArray.push(listing);
|
|
|
|
+ } else {
|
|
|
|
+ listing[1] = parseFloat(listing[1]);
|
|
|
|
+ pkgNumSortArray.push(listing);
|
|
|
|
+ };
|
|
|
|
+ })
|
|
|
|
+ sortedStringPkgArray = pkgStringSortArray.sort(function(a, b) {
|
|
|
|
+ const nameA = a[1].toUpperCase(); // ignore upper and lowercase
|
|
|
|
+ const nameB = b[1].toUpperCase(); // ignore upper and lowercase
|
|
|
|
+ if (nameA < nameB) { return -1; };
|
|
|
|
+ if (nameA > nameB) { return 1; };
|
|
|
|
+ return 0; // names must be equal
|
|
|
|
+ });
|
|
|
|
+ sortedNumPkgArray = pkgNumSortArray.sort(function(a, b) {
|
|
|
|
+ return a[1] - b[1];
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ let triangleUp = String.fromCodePoint(32, 9652);
|
|
|
|
+ let triangleDown = String.fromCodePoint(32, 9662);
|
|
|
|
+ let columnName = document.getElementById(sortLabel);
|
|
|
|
+
|
|
|
|
+ if (columnName.lastElementChild.innerText == triangleDown) {
|
|
|
|
+ columnName.lastElementChild.innerText = triangleUp;
|
|
|
|
+ sortedStringPkgArray.reverse();
|
|
|
|
+ sortedNumPkgArray.reverse();
|
|
|
|
+ sortedPkgArray = sortedNumPkgArray.concat(sortedStringPkgArray)
|
|
|
|
+ } else {
|
|
|
|
+ columnName.lastElementChild.innerText = triangleDown;
|
|
|
|
+ sortedPkgArray = sortedStringPkgArray.concat(sortedNumPkgArray)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sortedPkgArray.forEach((listing) => {
|
|
|
|
+ let row = Array.from(document.getElementsByClassName(listing[0]));
|
|
|
|
+ let packageGrid = document.getElementById("package-grid");
|
|
|
|
+ row.forEach((element) => { packageGrid.append(element)});
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
+</script>
|
|
|
|
|
|
-td.cpe-ok {
|
|
|
|
- background: #d2ffc4;
|
|
|
|
-}
|
|
|
|
|
|
+<style>
|
|
|
|
|
|
-td.cpe-nok {
|
|
|
|
- background: #ff9a69;
|
|
|
|
|
|
+.label {
|
|
|
|
+ position: sticky;
|
|
|
|
+ top: 1px;
|
|
}
|
|
}
|
|
-
|
|
|
|
-td.cpe-unknown {
|
|
|
|
- background: #ffd870;
|
|
|
|
|
|
+.label{
|
|
|
|
+ background: white;
|
|
|
|
+ padding: 10px 2px 10px 2px;
|
|
}
|
|
}
|
|
-
|
|
|
|
-td.cve-ok {
|
|
|
|
- background: #d2ffc4;
|
|
|
|
|
|
+#package-grid, #results-grid {
|
|
|
|
+ display: grid;
|
|
|
|
+ grid-gap: 2px;
|
|
|
|
+ grid-template-columns: 1fr repeat(12, min-content);
|
|
}
|
|
}
|
|
-
|
|
|
|
-td.cve-nok {
|
|
|
|
- background: #ff9a69;
|
|
|
|
|
|
+#results-grid {
|
|
|
|
+ grid-template-columns: 3fr 1fr;
|
|
}
|
|
}
|
|
-
|
|
|
|
-td.cve-unknown {
|
|
|
|
- background: #ffd870;
|
|
|
|
|
|
+.data {
|
|
|
|
+ border: solid 1px gray;
|
|
}
|
|
}
|
|
-
|
|
|
|
-td.cve_ignored {
|
|
|
|
- background: #ccc;
|
|
|
|
|
|
+.centered {
|
|
|
|
+ text-align: center;
|
|
}
|
|
}
|
|
|
|
+ .wrong, .lotsofpatches, .invalid_url, .version-needs-update, .cpe-nok, .cve-nok {
|
|
|
|
+ background: #ff9a69;
|
|
|
|
+ }
|
|
|
|
+ .correct, .nopatches, .good_url, .version-good, .cpe-ok, .cve-ok {
|
|
|
|
+ background: #d2ffc4;
|
|
|
|
+ }
|
|
|
|
+ .somepatches, .missing_url, .version-unknown, .cpe-unknown, .cve-unknown {
|
|
|
|
+ background: #ffd870;
|
|
|
|
+ }
|
|
|
|
+ .cve_ignored, .version-error {
|
|
|
|
+ background: #ccc;
|
|
|
|
+ }
|
|
|
|
|
|
</style>
|
|
</style>
|
|
|
|
+
|
|
<title>Statistics of Buildroot packages</title>
|
|
<title>Statistics of Buildroot packages</title>
|
|
|
|
+
|
|
</head>
|
|
</head>
|
|
|
|
|
|
|
|
+<body>
|
|
|
|
+
|
|
<a href=\"#results\">Results</a><br/>
|
|
<a href=\"#results\">Results</a><br/>
|
|
|
|
|
|
<p id=\"sortable_hint\"></p>
|
|
<p id=\"sortable_hint\"></p>
|
|
@@ -808,13 +832,13 @@ td.cve_ignored {
|
|
|
|
|
|
|
|
|
|
html_footer = """
|
|
html_footer = """
|
|
-</body>
|
|
|
|
<script>
|
|
<script>
|
|
-if (typeof sorttable === \"object\") {
|
|
|
|
- document.getElementById(\"sortable_hint\").innerHTML =
|
|
|
|
- \"hint: the table can be sorted by clicking the column headers\"
|
|
|
|
|
|
+if (typeof sortGrid === "function") {
|
|
|
|
+ document.getElementById("sortable_hint").innerHTML =
|
|
|
|
+ "hint: the table can be sorted by clicking the column headers"
|
|
}
|
|
}
|
|
</script>
|
|
</script>
|
|
|
|
+</body>
|
|
</html>
|
|
</html>
|
|
"""
|
|
"""
|
|
|
|
|
|
@@ -841,73 +865,87 @@ def boolean_str(b):
|
|
|
|
|
|
|
|
|
|
def dump_html_pkg(f, pkg):
|
|
def dump_html_pkg(f, pkg):
|
|
- f.write(" <tr>\n")
|
|
|
|
- f.write(" <td>%s</td>\n" % pkg.path)
|
|
|
|
-
|
|
|
|
|
|
+ f.write( f'<div id=\"package_{pkg.name}\" \
|
|
|
|
+ class=\"package data {pkg.name}\">{pkg.path}</div>\n')
|
|
# Patch count
|
|
# Patch count
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'patch_count_{pkg.name}'
|
|
|
|
+ div_class = ["centered patch_count data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.patch_count == 0:
|
|
if pkg.patch_count == 0:
|
|
- td_class.append("nopatches")
|
|
|
|
|
|
+ div_class.append("nopatches")
|
|
elif pkg.patch_count < 5:
|
|
elif pkg.patch_count < 5:
|
|
- td_class.append("somepatches")
|
|
|
|
|
|
+ div_class.append("somepatches")
|
|
else:
|
|
else:
|
|
- td_class.append("lotsofpatches")
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), str(pkg.patch_count)))
|
|
|
|
|
|
+ div_class.append("lotsofpatches")
|
|
|
|
+ f.write( f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)} \
|
|
|
|
+ \">{str(pkg.patch_count)}</div>\n')
|
|
|
|
|
|
# Infrastructure
|
|
# Infrastructure
|
|
|
|
+ data_field_id = f'infrastructure_{pkg.name}'
|
|
infra = infra_str(pkg.infras)
|
|
infra = infra_str(pkg.infras)
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ div_class = ["centered infrastructure data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if infra == "Unknown":
|
|
if infra == "Unknown":
|
|
- td_class.append("wrong")
|
|
|
|
|
|
+ div_class.append("wrong")
|
|
else:
|
|
else:
|
|
- td_class.append("correct")
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), infra_str(pkg.infras)))
|
|
|
|
|
|
+ div_class.append("correct")
|
|
|
|
+ f.write( f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)} \
|
|
|
|
+ \">{infra_str(pkg.infras)}</div>\n')
|
|
|
|
|
|
# License
|
|
# License
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'license_{pkg.name}'
|
|
|
|
+ div_class = ["centered license data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.is_status_ok('license'):
|
|
if pkg.is_status_ok('license'):
|
|
- td_class.append("correct")
|
|
|
|
|
|
+ div_class.append("correct")
|
|
else:
|
|
else:
|
|
- td_class.append("wrong")
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), boolean_str(pkg.is_status_ok('license'))))
|
|
|
|
|
|
+ div_class.append("wrong")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)} \
|
|
|
|
+ \">{boolean_str(pkg.is_status_ok("license"))}</div>\n')
|
|
|
|
|
|
# License files
|
|
# License files
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'license_files_{pkg.name}'
|
|
|
|
+ div_class = ["centered license_files data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.is_status_ok('license-files'):
|
|
if pkg.is_status_ok('license-files'):
|
|
- td_class.append("correct")
|
|
|
|
|
|
+ div_class.append("correct")
|
|
else:
|
|
else:
|
|
- td_class.append("wrong")
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), boolean_str(pkg.is_status_ok('license-files'))))
|
|
|
|
|
|
+ div_class.append("wrong")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)} \
|
|
|
|
+ \">{boolean_str(pkg.is_status_ok("license-files"))}</div>\n')
|
|
|
|
|
|
# Hash
|
|
# Hash
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'hash_file_{pkg.name}'
|
|
|
|
+ div_class = ["centered hash_file data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.is_status_ok('hash'):
|
|
if pkg.is_status_ok('hash'):
|
|
- td_class.append("correct")
|
|
|
|
|
|
+ div_class.append("correct")
|
|
else:
|
|
else:
|
|
- td_class.append("wrong")
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), boolean_str(pkg.is_status_ok('hash'))))
|
|
|
|
|
|
+ div_class.append("wrong")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)} \
|
|
|
|
+ \">{boolean_str(pkg.is_status_ok("hash"))}</div>\n')
|
|
|
|
|
|
# Current version
|
|
# Current version
|
|
|
|
+ data_field_id = f'current_version_{pkg.name}'
|
|
if len(pkg.current_version) > 20:
|
|
if len(pkg.current_version) > 20:
|
|
current_version = pkg.current_version[:20] + "..."
|
|
current_version = pkg.current_version[:20] + "..."
|
|
else:
|
|
else:
|
|
current_version = pkg.current_version
|
|
current_version = pkg.current_version
|
|
- f.write(" <td class=\"centered\">%s</td>\n" % current_version)
|
|
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" \
|
|
|
|
+ class=\"centered current_version data {pkg.name}\">{current_version}</div>\n')
|
|
|
|
|
|
# Latest version
|
|
# Latest version
|
|
|
|
+ data_field_id = f'latest_version_{pkg.name}'
|
|
|
|
+ div_class.append(pkg.name)
|
|
|
|
+ div_class.append("latest_version data")
|
|
if pkg.latest_version['status'] == RM_API_STATUS_ERROR:
|
|
if pkg.latest_version['status'] == RM_API_STATUS_ERROR:
|
|
- td_class.append("version-error")
|
|
|
|
|
|
+ div_class.append("version-error")
|
|
if pkg.latest_version['version'] is None:
|
|
if pkg.latest_version['version'] is None:
|
|
- td_class.append("version-unknown")
|
|
|
|
|
|
+ div_class.append("version-unknown")
|
|
elif pkg.latest_version['version'] != pkg.current_version:
|
|
elif pkg.latest_version['version'] != pkg.current_version:
|
|
- td_class.append("version-needs-update")
|
|
|
|
|
|
+ div_class.append("version-needs-update")
|
|
else:
|
|
else:
|
|
- td_class.append("version-good")
|
|
|
|
|
|
+ div_class.append("version-good")
|
|
|
|
|
|
if pkg.latest_version['status'] == RM_API_STATUS_ERROR:
|
|
if pkg.latest_version['status'] == RM_API_STATUS_ERROR:
|
|
latest_version_text = "<b>Error</b>"
|
|
latest_version_text = "<b>Error</b>"
|
|
@@ -927,74 +965,81 @@ def dump_html_pkg(f, pkg):
|
|
else:
|
|
else:
|
|
latest_version_text += "found by guess"
|
|
latest_version_text += "found by guess"
|
|
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), latest_version_text))
|
|
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">{latest_version_text}</div>\n')
|
|
|
|
|
|
# Warnings
|
|
# Warnings
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'warnings_{pkg.name}'
|
|
|
|
+ div_class = ["centered warnings data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.warnings == 0:
|
|
if pkg.warnings == 0:
|
|
- td_class.append("correct")
|
|
|
|
|
|
+ div_class.append("correct")
|
|
else:
|
|
else:
|
|
- td_class.append("wrong")
|
|
|
|
- f.write(" <td class=\"%s\">%d</td>\n" %
|
|
|
|
- (" ".join(td_class), pkg.warnings))
|
|
|
|
|
|
+ div_class.append("wrong")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">{pkg.warnings}</div>\n')
|
|
|
|
|
|
# URL status
|
|
# URL status
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'upstream_url_{pkg.name}'
|
|
|
|
+ div_class = ["centered upstream_url data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
url_str = pkg.status['url'][1]
|
|
url_str = pkg.status['url'][1]
|
|
if pkg.status['url'][0] in ("error", "warning"):
|
|
if pkg.status['url'][0] in ("error", "warning"):
|
|
- td_class.append("missing_url")
|
|
|
|
|
|
+ div_class.append("missing_url")
|
|
if pkg.status['url'][0] == "error":
|
|
if pkg.status['url'][0] == "error":
|
|
- td_class.append("invalid_url")
|
|
|
|
- url_str = "<a href=%s>%s</a>" % (pkg.url, pkg.status['url'][1])
|
|
|
|
|
|
+ div_class.append("invalid_url")
|
|
|
|
+ url_str = "<a href=\"%s\">%s</a>" % (pkg.url, pkg.status['url'][1])
|
|
else:
|
|
else:
|
|
- td_class.append("good_url")
|
|
|
|
- url_str = "<a href=%s>Link</a>" % pkg.url
|
|
|
|
- f.write(" <td class=\"%s\">%s</td>\n" %
|
|
|
|
- (" ".join(td_class), url_str))
|
|
|
|
|
|
+ div_class.append("good_url")
|
|
|
|
+ url_str = "<a href=\"%s\">Link</a>" % pkg.url
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">{url_str}</div>\n')
|
|
|
|
|
|
# CVEs
|
|
# CVEs
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'cves_{pkg.name}'
|
|
|
|
+ div_class = ["centered cves data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.is_status_ok("cve"):
|
|
if pkg.is_status_ok("cve"):
|
|
- td_class.append("cve-ok")
|
|
|
|
|
|
+ div_class.append("cve-ok")
|
|
elif pkg.is_status_error("cve"):
|
|
elif pkg.is_status_error("cve"):
|
|
- td_class.append("cve-nok")
|
|
|
|
|
|
+ div_class.append("cve-nok")
|
|
elif pkg.is_status_na("cve") and not pkg.is_actual_package:
|
|
elif pkg.is_status_na("cve") and not pkg.is_actual_package:
|
|
- td_class.append("cve-ok")
|
|
|
|
|
|
+ div_class.append("cve-ok")
|
|
else:
|
|
else:
|
|
- td_class.append("cve-unknown")
|
|
|
|
- f.write(" <td class=\"%s\">\n" % " ".join(td_class))
|
|
|
|
|
|
+ div_class.append("cve-unknown")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">\n')
|
|
if pkg.is_status_error("cve"):
|
|
if pkg.is_status_error("cve"):
|
|
for cve in pkg.cves:
|
|
for cve in pkg.cves:
|
|
- f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s<br/>\n" % (cve, cve))
|
|
|
|
|
|
+ f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s</a><br/>\n" % (cve, cve))
|
|
for cve in pkg.unsure_cves:
|
|
for cve in pkg.unsure_cves:
|
|
- f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s <i>(unsure)</i><br/>\n" % (cve, cve))
|
|
|
|
|
|
+ f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s <i>(unsure)</i></a><br/>\n" % (cve, cve))
|
|
elif pkg.is_status_na("cve"):
|
|
elif pkg.is_status_na("cve"):
|
|
f.write(" %s" % pkg.status['cve'][1])
|
|
f.write(" %s" % pkg.status['cve'][1])
|
|
else:
|
|
else:
|
|
f.write(" N/A\n")
|
|
f.write(" N/A\n")
|
|
- f.write(" </td>\n")
|
|
|
|
|
|
+ f.write(" </div>\n")
|
|
|
|
|
|
# CVEs Ignored
|
|
# CVEs Ignored
|
|
- td_class = ["centered"]
|
|
|
|
|
|
+ data_field_id = f'ignored_cves_{pkg.name}'
|
|
|
|
+ div_class = ["centered data ignored_cves"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.ignored_cves:
|
|
if pkg.ignored_cves:
|
|
- td_class.append("cve_ignored")
|
|
|
|
- f.write(" <td class=\"%s\">\n" % " ".join(td_class))
|
|
|
|
|
|
+ div_class.append("cve_ignored")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">\n')
|
|
for ignored_cve in pkg.ignored_cves:
|
|
for ignored_cve in pkg.ignored_cves:
|
|
- f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s<br/>\n" % (ignored_cve, ignored_cve))
|
|
|
|
- f.write(" </td>\n")
|
|
|
|
|
|
+ f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s</a><br/>\n" % (ignored_cve, ignored_cve))
|
|
|
|
+ f.write(" </div>\n")
|
|
|
|
|
|
# CPE ID
|
|
# CPE ID
|
|
- td_class = ["left"]
|
|
|
|
|
|
+ data_field_id = f'cpe_id_{pkg.name}'
|
|
|
|
+ div_class = ["left cpe_id data"]
|
|
|
|
+ div_class.append(pkg.name)
|
|
if pkg.is_status_ok("cpe"):
|
|
if pkg.is_status_ok("cpe"):
|
|
- td_class.append("cpe-ok")
|
|
|
|
|
|
+ div_class.append("cpe-ok")
|
|
elif pkg.is_status_error("cpe"):
|
|
elif pkg.is_status_error("cpe"):
|
|
- td_class.append("cpe-nok")
|
|
|
|
|
|
+ div_class.append("cpe-nok")
|
|
elif pkg.is_status_na("cpe") and not pkg.is_actual_package:
|
|
elif pkg.is_status_na("cpe") and not pkg.is_actual_package:
|
|
- td_class.append("cpe-ok")
|
|
|
|
|
|
+ div_class.append("cpe-ok")
|
|
else:
|
|
else:
|
|
- td_class.append("cpe-unknown")
|
|
|
|
- f.write(" <td class=\"%s\">\n" % " ".join(td_class))
|
|
|
|
|
|
+ div_class.append("cpe-unknown")
|
|
|
|
+ f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">\n')
|
|
if pkg.cpeid:
|
|
if pkg.cpeid:
|
|
f.write(" <code>%s</code>\n" % pkg.cpeid)
|
|
f.write(" <code>%s</code>\n" % pkg.cpeid)
|
|
if not pkg.is_status_ok("cpe"):
|
|
if not pkg.is_status_ok("cpe"):
|
|
@@ -1008,79 +1053,75 @@ def dump_html_pkg(f, pkg):
|
|
else:
|
|
else:
|
|
f.write(" %s\n" % pkg.status['cpe'][1])
|
|
f.write(" %s\n" % pkg.status['cpe'][1])
|
|
|
|
|
|
- f.write(" </td>\n")
|
|
|
|
-
|
|
|
|
- f.write(" </tr>\n")
|
|
|
|
|
|
+ f.write(" </div>\n")
|
|
|
|
|
|
|
|
|
|
def dump_html_all_pkgs(f, packages):
|
|
def dump_html_all_pkgs(f, packages):
|
|
f.write("""
|
|
f.write("""
|
|
-<table class=\"sortable\">
|
|
|
|
-<tr>
|
|
|
|
-<td>Package</td>
|
|
|
|
-<td class=\"centered\">Patch count</td>
|
|
|
|
-<td class=\"centered\">Infrastructure</td>
|
|
|
|
-<td class=\"centered\">License</td>
|
|
|
|
-<td class=\"centered\">License files</td>
|
|
|
|
-<td class=\"centered\">Hash file</td>
|
|
|
|
-<td class=\"centered\">Current version</td>
|
|
|
|
-<td class=\"centered\">Latest version</td>
|
|
|
|
-<td class=\"centered\">Warnings</td>
|
|
|
|
-<td class=\"centered\">Upstream URL</td>
|
|
|
|
-<td class=\"centered\">CVEs</td>
|
|
|
|
-<td class=\"centered\">CVEs Ignored</td>
|
|
|
|
-<td class=\"centered\">CPE ID</td>
|
|
|
|
-</tr>
|
|
|
|
|
|
+<div id=\"package-grid\">
|
|
|
|
+<div style="grid-column: 1;" onclick="sortGrid(this.id)" id=\"package\" class=\"package data label\"><span>Package</span><span></span></div>
|
|
|
|
+<div style="grid-column: 2;" onclick="sortGrid(this.id)" id=\"patch_count\" class=\"centered patch_count data label\"><span>Patch count</span><span></span></div>
|
|
|
|
+<div style="grid-column: 3;" onclick="sortGrid(this.id)" id=\"infrastructure\" class=\"centered infrastructure data label\">Infrastructure<span></span></div>
|
|
|
|
+<div style="grid-column: 4;" onclick="sortGrid(this.id)" id=\"license\" class=\"centered license data label\"><span>License</span><span></span></div>
|
|
|
|
+<div style="grid-column: 5;" onclick="sortGrid(this.id)" id=\"license_files\" class=\"centered license_files data label\"><span>License files</span><span></span></div>
|
|
|
|
+<div style="grid-column: 6;" onclick="sortGrid(this.id)" id=\"hash_file\" class=\"centered hash_file data label\"><span>Hash file</span><span></span></div>
|
|
|
|
+<div style="grid-column: 7;" onclick="sortGrid(this.id)" id=\"current_version\" class=\"centered current_version data label\"><span>Current version</span><span></span></div>
|
|
|
|
+<div style="grid-column: 8;" onclick="sortGrid(this.id)" id=\"latest_version\" class=\"centered latest_version data label\"><span>Latest version</span><span></span></div>
|
|
|
|
+<div style="grid-column: 9;" onclick="sortGrid(this.id)" id=\"warnings\" class=\"centered warnings data label\"><span>Warnings</span><span></span></div>
|
|
|
|
+<div style="grid-column: 10;" onclick="sortGrid(this.id)" id=\"upstream_url\" class=\"centered upstream_url data label\"><span>Upstream URL</span><span></span></div>
|
|
|
|
+<div style="grid-column: 11;" onclick="sortGrid(this.id)" id=\"cves\" class=\"centered cves data label\"><span>CVEs</span><span></span></div>
|
|
|
|
+<div style="grid-column: 12;" onclick="sortGrid(this.id)" id=\"ignored_cves\" class=\"centered ignored_cves data label\"><span>CVEs Ignored</span><span></span></div>
|
|
|
|
+<div style="grid-column: 13;" onclick="sortGrid(this.id)" id=\"cpe_id\" class=\"centered cpe_id data label\"><span>CPE ID</span><span></span></div>
|
|
""")
|
|
""")
|
|
for pkg in sorted(packages):
|
|
for pkg in sorted(packages):
|
|
dump_html_pkg(f, pkg)
|
|
dump_html_pkg(f, pkg)
|
|
- f.write("</table>")
|
|
|
|
|
|
+ f.write("</div>")
|
|
|
|
|
|
|
|
|
|
def dump_html_stats(f, stats):
|
|
def dump_html_stats(f, stats):
|
|
f.write("<a id=\"results\"></a>\n")
|
|
f.write("<a id=\"results\"></a>\n")
|
|
- f.write("<table>\n")
|
|
|
|
|
|
+ f.write("<div class=\"data\" id=\"results-grid\">\n")
|
|
infras = [infra[6:] for infra in stats.keys() if infra.startswith("infra-")]
|
|
infras = [infra[6:] for infra in stats.keys() if infra.startswith("infra-")]
|
|
for infra in infras:
|
|
for infra in infras:
|
|
- f.write(" <tr><td>Packages using the <i>%s</i> infrastructure</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages using the <i>%s</i> infrastructure</div><div class=\"data\">%s</div>\n" %
|
|
(infra, stats["infra-%s" % infra]))
|
|
(infra, stats["infra-%s" % infra]))
|
|
- f.write(" <tr><td>Packages having license information</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages having license information</div><div class=\"data\">%s</div>\n" %
|
|
stats["license"])
|
|
stats["license"])
|
|
- f.write(" <tr><td>Packages not having license information</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages not having license information</div><div class=\"data\">%s</div>\n" %
|
|
stats["no-license"])
|
|
stats["no-license"])
|
|
- f.write(" <tr><td>Packages having license files information</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages having license files information</div><div class=\"data\">%s</div>\n" %
|
|
stats["license-files"])
|
|
stats["license-files"])
|
|
- f.write(" <tr><td>Packages not having license files information</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages not having license files information</div><div class=\"data\">%s</div>\n" %
|
|
stats["no-license-files"])
|
|
stats["no-license-files"])
|
|
- f.write(" <tr><td>Packages having a hash file</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages having a hash file</div><div class=\"data\">%s</div>\n" %
|
|
stats["hash"])
|
|
stats["hash"])
|
|
- f.write(" <tr><td>Packages not having a hash file</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Packages not having a hash file</div><div class=\"data\">%s</div>\n" %
|
|
stats["no-hash"])
|
|
stats["no-hash"])
|
|
- f.write(" <tr><td>Total number of patches</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write(" <div class=\"data\">Total number of patches</div><div class=\"data\">%s</div>\n" %
|
|
stats["patches"])
|
|
stats["patches"])
|
|
- f.write("<tr><td>Packages having a mapping on <i>release-monitoring.org</i></td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages having a mapping on <i>release-monitoring.org</i></div><div class=\"data\">%s</div>\n" %
|
|
stats["rmo-mapping"])
|
|
stats["rmo-mapping"])
|
|
- f.write("<tr><td>Packages lacking a mapping on <i>release-monitoring.org</i></td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages lacking a mapping on <i>release-monitoring.org</i></div><div class=\"data\">%s</div>\n" %
|
|
stats["rmo-no-mapping"])
|
|
stats["rmo-no-mapping"])
|
|
- f.write("<tr><td>Packages that are up-to-date</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages that are up-to-date</div><div class=\"data\">%s</div>\n" %
|
|
stats["version-uptodate"])
|
|
stats["version-uptodate"])
|
|
- f.write("<tr><td>Packages that are not up-to-date</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages that are not up-to-date</div><div class=\"data\">%s</div>\n" %
|
|
stats["version-not-uptodate"])
|
|
stats["version-not-uptodate"])
|
|
- f.write("<tr><td>Packages with no known upstream version</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages with no known upstream version</div><div class=\"data\">%s</div>\n" %
|
|
stats["version-unknown"])
|
|
stats["version-unknown"])
|
|
- f.write("<tr><td>Packages affected by CVEs</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages affected by CVEs</div><div class=\"data\">%s</div>\n" %
|
|
stats["pkg-cves"])
|
|
stats["pkg-cves"])
|
|
- f.write("<tr><td>Total number of CVEs affecting all packages</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Total number of CVEs affecting all packages</div><div class=\"data\">%s</div>\n" %
|
|
stats["total-cves"])
|
|
stats["total-cves"])
|
|
- f.write("<tr><td>Packages affected by unsure CVEs</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages affected by unsure CVEs</div><div class=\"data\">%s</div>\n" %
|
|
stats["pkg-unsure-cves"])
|
|
stats["pkg-unsure-cves"])
|
|
- f.write("<tr><td>Total number of unsure CVEs affecting all packages</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Total number of unsure CVEs affecting all packages</div><div class=\"data\">%s</div>\n" %
|
|
stats["total-unsure-cves"])
|
|
stats["total-unsure-cves"])
|
|
- f.write("<tr><td>Packages with CPE ID</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages with CPE ID</div><div class=\"data\">%s</div>\n" %
|
|
stats["cpe-id"])
|
|
stats["cpe-id"])
|
|
- f.write("<tr><td>Packages without CPE ID</td><td>%s</td></tr>\n" %
|
|
|
|
|
|
+ f.write("<div class=\"data\">Packages without CPE ID</div><div class=\"data\">%s</div>\n" %
|
|
stats["no-cpe-id"])
|
|
stats["no-cpe-id"])
|
|
- f.write("</table>\n")
|
|
|
|
|
|
+ f.write("</div>\n")
|
|
|
|
|
|
|
|
|
|
def dump_html_gen_info(f, date, commit):
|
|
def dump_html_gen_info(f, date, commit):
|