mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 05:40:11 +01:00
* move csaf_searcher to a lower prio place * Adjust wording * Grammar fix #2 'this is work in progress' -> 'This is a work in progress'... --------- Co-authored-by: JanHoefelmeyer <hoefelmeyer.jan@gmail.com>
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
// Package main implements a simple demo program to
|
|
// work with the csaf_distribution library.
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/csaf-poc/csaf_distribution/v3/csaf"
|
|
)
|
|
|
|
func main() {
|
|
flag.Usage = func() {
|
|
fmt.Fprintf(flag.CommandLine.Output(),
|
|
"Usage:\n %s [OPTIONS] files...\n\nOptions:\n", os.Args[0])
|
|
flag.PrintDefaults()
|
|
}
|
|
idsString := flag.String("p", "", "ID1,ID2,...")
|
|
flag.Parse()
|
|
|
|
files := flag.Args()
|
|
if len(files) == 0 {
|
|
log.Println("No files given.")
|
|
return
|
|
}
|
|
if err := run(files, *idsString); err != nil {
|
|
log.Fatalf("error: %v\n", err)
|
|
}
|
|
}
|
|
|
|
// run prints PURLs belonging to the given Product IDs.
|
|
func run(files []string, ids string) error {
|
|
|
|
uf := newURLFinder(strings.Split(ids, ","))
|
|
|
|
for _, file := range files {
|
|
adv, err := csaf.LoadAdvisory(file)
|
|
if err != nil {
|
|
return fmt.Errorf("loading %q failed: %w", file, err)
|
|
}
|
|
uf.findURLs(adv)
|
|
uf.dumpURLs()
|
|
uf.clear()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// urlFinder helps to find the URLs of a set of product ids in advisories.
|
|
type urlFinder struct {
|
|
ids []csaf.ProductID
|
|
urls [][]csaf.PURL
|
|
}
|
|
|
|
// newURLFinder creates a new urlFinder for given ids.
|
|
func newURLFinder(ids []string) *urlFinder {
|
|
uf := &urlFinder{
|
|
ids: make([]csaf.ProductID, len(ids)),
|
|
urls: make([][]csaf.PURL, len(ids)),
|
|
}
|
|
for i := range uf.ids {
|
|
uf.ids[i] = csaf.ProductID(ids[i])
|
|
}
|
|
return uf
|
|
}
|
|
|
|
// clear resets the url finder after a run on an advisory.
|
|
func (uf *urlFinder) clear() {
|
|
clear(uf.urls)
|
|
}
|
|
|
|
// dumpURLs dumps the found URLs to stdout.
|
|
func (uf *urlFinder) dumpURLs() {
|
|
for i, urls := range uf.urls {
|
|
if len(urls) == 0 {
|
|
continue
|
|
}
|
|
fmt.Printf("Found URLs for %s:\n", uf.ids[i])
|
|
for j, url := range urls {
|
|
fmt.Printf("%d. %s\n", j+1, url)
|
|
}
|
|
}
|
|
}
|
|
|
|
// findURLs find the URLs in an advisory.
|
|
func (uf *urlFinder) findURLs(adv *csaf.Advisory) {
|
|
tree := adv.ProductTree
|
|
if tree == nil {
|
|
return
|
|
}
|
|
|
|
// If we have found it and we have a valid URL add unique.
|
|
add := func(idx int, h *csaf.ProductIdentificationHelper) {
|
|
if idx != -1 && h != nil && h.PURL != nil &&
|
|
!slices.Contains(uf.urls[idx], *h.PURL) {
|
|
uf.urls[idx] = append(uf.urls[idx], *h.PURL)
|
|
}
|
|
}
|
|
|
|
// First iterate over full product names.
|
|
if names := tree.FullProductNames; names != nil {
|
|
for _, name := range *names {
|
|
if name != nil && name.ProductID != nil {
|
|
add(slices.Index(uf.ids, *name.ProductID), name.ProductIdentificationHelper)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Second traverse the branches recursively.
|
|
var recBranch func(*csaf.Branch)
|
|
recBranch = func(b *csaf.Branch) {
|
|
if p := b.Product; p != nil && p.ProductID != nil {
|
|
add(slices.Index(uf.ids, *p.ProductID), p.ProductIdentificationHelper)
|
|
}
|
|
for _, c := range b.Branches {
|
|
recBranch(c)
|
|
}
|
|
}
|
|
for _, b := range tree.Branches {
|
|
recBranch(b)
|
|
}
|
|
}
|