github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/php/parse_composer_lock.go (about)

     1  package php
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  
    10  	"github.com/anchore/syft/internal/unknown"
    11  	"github.com/anchore/syft/syft/artifact"
    12  	"github.com/anchore/syft/syft/file"
    13  	"github.com/anchore/syft/syft/pkg"
    14  	"github.com/anchore/syft/syft/pkg/cataloger/generic"
    15  )
    16  
    17  var _ generic.Parser = parseComposerLock
    18  
    19  type parsedLockData struct {
    20  	License []string `json:"license"`
    21  	pkg.PhpComposerLockEntry
    22  }
    23  
    24  type composerLock struct {
    25  	Packages   []parsedLockData `json:"packages"`
    26  	PackageDev []parsedLockData `json:"packages-dev"` // TODO: these are not currently included as packages in the SBOM... should they be?
    27  }
    28  
    29  // parseComposerLock is a parser function for Composer.lock contents, returning "Default" php packages discovered.
    30  func parseComposerLock(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    31  	pkgs := make([]pkg.Package, 0)
    32  	dec := json.NewDecoder(reader)
    33  
    34  	for {
    35  		var lock composerLock
    36  		if err := dec.Decode(&lock); errors.Is(err, io.EOF) {
    37  			break
    38  		} else if err != nil {
    39  			return nil, nil, fmt.Errorf("failed to parse composer.lock file: %w", err)
    40  		}
    41  		for _, pd := range lock.Packages {
    42  			pkgs = append(
    43  				pkgs,
    44  				newComposerLockPackage(
    45  					ctx,
    46  					pd,
    47  					reader.Location,
    48  				),
    49  			)
    50  		}
    51  	}
    52  
    53  	return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages")
    54  }