feat: Add Wordpress cataloger (#2218)

* Closes #1911 Wordpress cataloger

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed a few unit tests and static analizer notices

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated `README.md`

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed `golangci-lint` notices
Added integration test for `wordpress-plugin`

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed `gosimports` notices

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated `json schema` version

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed CLI tests, increased expected package count

Signed-off-by: disc <a.hacicheant@gmail.com>

* Read first 4Kb of a plugins file's content

Signed-off-by: disc <a.hacicheant@gmail.com>

* replace JSON schema version

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* change wording on source info for wordpress packages

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* Minor changes after a huge refactoring

Signed-off-by: disc <a.hacicheant@gmail.com>

* Removed unused files

Signed-off-by: disc <a.hacicheant@gmail.com>

* Updated schema

Signed-off-by: disc <a.hacicheant@gmail.com>

* Fixed integration tests

Signed-off-by: disc <a.hacicheant@gmail.com>

* fix integration tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* Renamed `metadata.Name` to `metadata.PluginInstallDirectory`

Signed-off-by: disc <a.hacicheant@gmail.com>

* rename fields to be compliant with json conventions

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: disc <a.hacicheant@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alexandr Hacicheant
2024-02-14 16:03:25 +00:00
committed by GitHub
co-authored by Alex Goodman
parent 98b700e83c
commit 96ee2db875
30 changed files with 4852 additions and 9 deletions
@@ -0,0 +1,98 @@
package wordpress
import (
"context"
"fmt"
"path/filepath"
"regexp"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)
const contentBufferSize = 4096
var patterns = map[string]*regexp.Regexp{
// match example: "Plugin Name: WP Migration" ---> WP Migration
"name": regexp.MustCompile(`(?i)plugin name:\s*(?P<name>.+)`),
// match example: "Version: 5.3" ---> 5.3
"version": regexp.MustCompile(`(?i)version:\s*(?P<version>[\d.]+)`),
// match example: "License: GPLv3" ---> GPLv3
"license": regexp.MustCompile(`(?i)license:\s*(?P<license>\w+)`),
// match example: "Author: MonsterInsights" ---> MonsterInsights
"author": regexp.MustCompile(`(?i)author:\s*(?P<author>.+)`),
// match example: "Author URI: https://servmask.com/" ---> https://servmask.com/
"author_uri": regexp.MustCompile(`(?i)author uri:\s*(?P<author_uri>.+)`),
}
type pluginData struct {
Licenses []string `mapstructure:"licenses" json:"licenses,omitempty"`
pkg.WordpressPluginEntry `mapstructure:",squash" json:",inline"`
}
func parseWordpressPluginFiles(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []pkg.Package
var fields = make(map[string]interface{})
buffer := make([]byte, contentBufferSize)
_, err := reader.Read(buffer)
if err != nil {
return nil, nil, fmt.Errorf("failed to read %s file: %w", reader.Location.Path(), err)
}
fileContent := string(buffer)
for field, pattern := range patterns {
matchMap := internal.MatchNamedCaptureGroups(pattern, fileContent)
if value := matchMap[field]; value != "" {
fields[field] = value
}
}
name, nameOk := fields["name"]
version, versionOk := fields["version"]
// get a plugin name from a plugin's directory name
pluginInstallDirectory := filepath.Base(filepath.Dir(reader.RealPath))
if nameOk && name != "" && versionOk && version != "" {
var metadata pluginData
metadata.PluginInstallDirectory = pluginInstallDirectory
author, authorOk := fields["author"]
if authorOk && author != "" {
metadata.Author = author.(string)
}
authorURI, authorURIOk := fields["author_uri"]
if authorURIOk && authorURI != "" {
metadata.AuthorURI = authorURI.(string)
}
license, licenseOk := fields["license"]
if licenseOk && license != "" {
licenses := make([]string, 0)
licenses = append(licenses, license.(string))
metadata.Licenses = licenses
}
pkgs = append(
pkgs,
newWordpressPluginPackage(
name.(string),
version.(string),
metadata,
reader.Location,
),
)
}
return pkgs, nil, nil
}