github.com/anchore/syft@v1.38.2/syft/format/purls/decoder.go (about) 1 package purls 2 3 import ( 4 "bufio" 5 "errors" 6 "fmt" 7 "io" 8 "strings" 9 10 "github.com/anchore/packageurl-go" 11 "github.com/anchore/syft/internal/log" 12 "github.com/anchore/syft/syft/format/internal" 13 "github.com/anchore/syft/syft/pkg" 14 "github.com/anchore/syft/syft/sbom" 15 ) 16 17 var _ sbom.FormatDecoder = (*decoder)(nil) 18 19 type decoder struct{} 20 21 func NewFormatDecoder() sbom.FormatDecoder { 22 return decoder{} 23 } 24 25 func (d decoder) Decode(r io.Reader) (*sbom.SBOM, sbom.FormatID, string, error) { 26 if r == nil { 27 return nil, "", "", fmt.Errorf("no reader provided") 28 } 29 s, err := toSyftModel(r) 30 return s, ID, version, err 31 } 32 33 func (d decoder) Identify(r io.Reader) (sbom.FormatID, string) { 34 if r == nil { 35 return "", "" 36 } 37 38 scanner := bufio.NewScanner(r) 39 for scanner.Scan() { 40 line := strings.TrimSpace(scanner.Text()) 41 if line == "" { 42 // skip whitespace only lines 43 continue 44 } 45 if strings.HasPrefix(line, "pkg:") { 46 _, err := packageurl.FromString(line) 47 if err != nil { 48 log.WithFields("error", err, "line", line).Debug("unable to parse purl") 49 continue 50 } 51 return ID, version 52 } 53 // not a purl, so we can't identify the format as a list of purls 54 return "", "" 55 } 56 57 return "", "" 58 } 59 60 func toSyftModel(r io.Reader) (*sbom.SBOM, error) { 61 var errs []error 62 pkgs := pkg.NewCollection() 63 64 scanner := bufio.NewScanner(r) 65 for scanner.Scan() { 66 line := strings.TrimSpace(scanner.Text()) 67 68 if line == "" { 69 continue 70 } 71 72 // skip invalid PURLs 73 _, err := packageurl.FromString(line) 74 if err != nil { 75 log.WithFields("error", err, "line", line).Debug("unable to parse purl") 76 continue 77 } 78 p := pkg.Package{ 79 // name, version and other properties set during Backfill 80 PURL: line, 81 } 82 83 internal.Backfill(&p) 84 p.SetID() 85 pkgs.Add(p) 86 } 87 88 return &sbom.SBOM{ 89 Artifacts: sbom.Artifacts{ 90 Packages: pkgs, 91 }, 92 }, errors.Join(errs...) 93 }