github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/php/parse_pecl_serialized.go (about)

     1  package php
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/elliotchance/phpserialize"
     9  
    10  	"github.com/anchore/syft/internal/log"
    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  // parsePeclSerialized is a parser function for PECL metadata contents, returning "Default" php packages discovered.
    18  func parsePeclSerialized(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    19  	var pkgs []pkg.Package
    20  	data, err := io.ReadAll(reader)
    21  
    22  	if err != nil {
    23  		return nil, nil, fmt.Errorf("failed to read file: %w", err)
    24  	}
    25  
    26  	metadata, err := phpserialize.UnmarshalAssociativeArray(
    27  		data,
    28  	)
    29  
    30  	if err != nil {
    31  		return nil, nil, fmt.Errorf("failed to parse pecl metadata file: %w", err)
    32  	}
    33  
    34  	name, ok := metadata["name"].(string)
    35  	if !ok {
    36  		return nil, nil, fmt.Errorf("failed to parse pecl package name: %w", err)
    37  	}
    38  
    39  	version := readStruct(metadata, "version", "release")
    40  	license := readStruct(metadata, "license", "_content")
    41  
    42  	pkgs = append(
    43  		pkgs,
    44  		newPeclPackage(
    45  			pkg.PhpPeclEntry{
    46  				Name:    name,
    47  				Version: version,
    48  				License: []string{
    49  					license,
    50  				},
    51  			},
    52  			reader.Location,
    53  		),
    54  	)
    55  
    56  	return pkgs, nil, nil
    57  }
    58  
    59  func readStruct(metadata any, fields ...string) string {
    60  	if len(fields) > 0 {
    61  		value, ok := metadata.(map[any]any)
    62  		if !ok {
    63  			log.Tracef("unable to read '%s' from: %v", fields[0], metadata)
    64  			return ""
    65  		}
    66  		return readStruct(value[fields[0]], fields[1:]...)
    67  	}
    68  	value, ok := metadata.(string)
    69  	if !ok {
    70  		log.Tracef("unable to read value from: %v", metadata)
    71  	}
    72  	return value
    73  }