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