github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/php/parse_installed_json.go (about)

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