package format
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/xmirrorsecurity/opensca-cli/v3/cmd/config"
"github.com/xmirrorsecurity/opensca-cli/v3/cmd/detail"
"github.com/xmirrorsecurity/opensca-cli/v3/opensca/logs"
)
type Report struct {
TaskInfo TaskInfo `json:"task_info" xml:"task_info"`
*detail.DepDetailGraph
}
type TaskInfo struct {
ToolVersion string `json:"tool_version" xml:"tool_version" `
AppName string `json:"app_name" xml:"app_name" `
Size int64 `json:"size" xml:"size" `
StartTime string `json:"start_time" xml:"start_time" `
EndTime string `json:"end_time" xml:"end_time" `
CostTime float64 `json:"cost_time" xml:"cost_time" `
ErrorString string `json:"error,omitempty" xml:"error,omitempty"`
}
func Save(report Report, output string) {
for out := range strings.SplitSeq(output, ",") {
logs.Infof("result save to %s", out)
switch filepath.Ext(out) {
case ".html":
Html(genReport(report), out)
case ".json":
if strings.HasSuffix(out, ".spdx.json") {
SpdxJson(report, out)
} else if strings.HasSuffix(out, ".dsdx.json") {
DsdxJson(report, out)
} else if strings.HasSuffix(out, ".cdx.json") {
CycloneDXJson(report, out)
} else if strings.HasSuffix(out, ".swid.json") {
SwidJson(report, out)
} else if strings.HasSuffix(out, ".bomsw.json") {
BomSWJson(report, out)
} else {
Json(genReport(report), out)
}
case ".sw", ".bom-sw", ".bomsw":
BomSWJson(report, out)
case ".dsdx":
Dsdx(report, out)
case ".spdx":
Spdx(report, out)
case ".xml":
if strings.HasSuffix(out, ".spdx.xml") {
SpdxXml(report, out)
} else if strings.HasSuffix(out, ".dsdx.xml") {
DsdxXml(report, out)
} else if strings.HasSuffix(out, ".cdx.xml") {
CycloneDXXml(report, out)
} else if strings.HasSuffix(out, ".swid.xml") {
SwidXml(report, out)
} else {
Xml(report, out)
}
case ".csv":
Csv(report, out)
case ".sqlite", ".db":
Sqlite(report, out)
case ".sarif":
Sarif(report, out)
default:
Json(genReport(report), out)
}
}
}
func genReport(report Report) Report {
optional := config.Conf().Optional
var newReport = report
if optional.VulnOnly {
var deps []*detail.DepDetailGraph
report.DepDetailGraph.ForEach(func(n *detail.DepDetailGraph) bool {
if len(n.Vulnerabilities) > 0 {
deps = append(deps, n)
}
return true
})
for _, d := range deps {
d.Children = nil
}
newReport.DepDetailGraph = &detail.DepDetailGraph{Children: deps}
}
return newReport
}
func outWrite(out string, do func(io.Writer) error) {
if out == "" {
do(os.Stdout)
return
}
if err := os.MkdirAll(filepath.Dir(out), 0777); err != nil {
logs.Warn(err)
fmt.Println(err)
return
}
w, err := os.Create(out)
if err != nil {
logs.Warn(err)
} else {
defer w.Close()
if err = do(w); err != nil {
logs.Warn(err)
}
}
}