github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/php/parse_installed_json.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  // Note: composer version 2 introduced a new structure for the installed.json file, so we support both
    20  type installedJSONComposerV2 struct {
    21  	Packages []parsedInstalledData `json:"packages"`
    22  }
    23  
    24  type parsedInstalledData struct {
    25  	License []string `json:"license"`
    26  	pkg.PhpComposerInstalledEntry
    27  }
    28  
    29  func (w *installedJSONComposerV2) UnmarshalJSON(data []byte) error {
    30  	type compv2 struct {
    31  		Packages []parsedInstalledData `json:"packages"`
    32  	}
    33  	compv2er := new(compv2)
    34  	err := json.Unmarshal(data, &compv2er)
    35  	if err != nil {
    36  		// If we had an err	or, we may be dealing with a composer v.1 installed.json
    37  		// which should be all arrays
    38  		var packages []parsedInstalledData
    39  		err := json.Unmarshal(data, &packages)
    40  		if err != nil {
    41  			return err
    42  		}
    43  		w.Packages = packages
    44  		return nil
    45  	}
    46  	w.Packages = compv2er.Packages
    47  	return nil
    48  }
    49  
    50  // parseInstalledJSON is a parser function for Composer.lock contents, returning "Default" php packages discovered.
    51  func parseInstalledJSON(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    52  	var pkgs []pkg.Package
    53  	dec := json.NewDecoder(reader)
    54  
    55  	for {
    56  		var lock installedJSONComposerV2
    57  		if err := dec.Decode(&lock); errors.Is(err, io.EOF) {
    58  			break
    59  		} else if err != nil {
    60  			return nil, nil, fmt.Errorf("failed to parse installed.json file: %w", err)
    61  		}
    62  		for _, pd := range lock.Packages {
    63  			pkgs = append(
    64  				pkgs,
    65  				newComposerInstalledPackage(
    66  					ctx,
    67  					pd,
    68  					reader.Location,
    69  				),
    70  			)
    71  		}
    72  	}
    73  
    74  	return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages")
    75  }