WFN格式
本页面描述了Well-Formed Name (WFN)格式的处理功能,这是CPE的内部标准表示格式。
WFN概述
Well-Formed Name (WFN) 是CPE的规范内部表示格式,提供了一种标准化的方式来表示CPE组件,使匹配和比较操作更加高效和可靠。
WFN结构
go
type WFN struct {
Part string // 组件类型 (a, h, o)
Vendor string // 供应商
Product string // 产品
Version string // 版本
Update string // 更新
Edition string // 版本
Language string // 语言
SoftwareEdition string // 软件版本
TargetSoftware string // 目标软件
TargetHardware string // 目标硬件
Other string // 其他
}
WFN特殊值
go
const (
WFNAny = "*" // 任意值
WFNNotApplicable = "-" // 不适用
)
WFN创建
NewWFN
创建新的WFN对象。
go
func NewWFN() *WFN
NewWFNFromCPE
从CPE对象创建WFN。
go
func NewWFNFromCPE(cpe *CPE) (*WFN, error)
示例:
go
// 创建空WFN
wfn := cpe.NewWFN()
wfn.Part = "a"
wfn.Vendor = "microsoft"
wfn.Product = "windows"
wfn.Version = "10"
// 从CPE创建WFN
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*")
wfn, err := cpe.NewWFNFromCPE(cpeObj)
if err != nil {
log.Fatal(err)
}
fmt.Printf("WFN: %s\n", wfn.String())
格式转换
CPEToWFN
将CPE对象转换为WFN。
go
func CPEToWFN(cpe *CPE) (*WFN, error)
WFNToCPE23
将WFN转换为CPE 2.3格式。
go
func WFNToCPE23(wfn *WFN) (string, error)
WFNToCPE22
将WFN转换为CPE 2.2格式。
go
func WFNToCPE22(wfn *WFN) (string, error)
示例:
go
// CPE到WFN转换
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:oracle:java:11.0.12:*:*:*:*:*:*:*")
wfn, err := cpe.CPEToWFN(cpeObj)
if err != nil {
log.Fatal(err)
}
fmt.Printf("原始CPE: %s\n", cpeObj.GetURI())
fmt.Printf("WFN格式: %s\n", wfn.String())
// WFN到CPE转换
cpe23, err := cpe.WFNToCPE23(wfn)
if err != nil {
log.Fatal(err)
}
cpe22, err := cpe.WFNToCPE22(wfn)
if err != nil {
log.Fatal(err)
}
fmt.Printf("转换为CPE 2.3: %s\n", cpe23)
fmt.Printf("转换为CPE 2.2: %s\n", cpe22)
WFN操作
String
获取WFN的字符串表示。
go
func (w *WFN) String() string
Clone
克隆WFN对象。
go
func (w *WFN) Clone() *WFN
Equals
比较两个WFN是否相等。
go
func (w *WFN) Equals(other *WFN) bool
示例:
go
wfn1 := &cpe.WFN{
Part: "a",
Vendor: "apache",
Product: "tomcat",
Version: "9.0.0",
}
wfn2 := wfn1.Clone()
wfn2.Version = "9.0.1"
fmt.Printf("WFN1: %s\n", wfn1.String())
fmt.Printf("WFN2: %s\n", wfn2.String())
fmt.Printf("相等: %t\n", wfn1.Equals(wfn2))
WFN验证
Validate
验证WFN的有效性。
go
func (w *WFN) Validate() error
ValidateWFN
验证WFN对象。
go
func ValidateWFN(wfn *WFN) error
IsValidWFNValue
检查值是否为有效的WFN值。
go
func IsValidWFNValue(value string) bool
示例:
go
wfn := &cpe.WFN{
Part: "a",
Vendor: "microsoft",
Product: "windows",
Version: "10",
}
// 验证WFN
err := wfn.Validate()
if err != nil {
fmt.Printf("WFN验证失败: %v\n", err)
} else {
fmt.Println("WFN验证通过")
}
// 验证单个值
if cpe.IsValidWFNValue("microsoft") {
fmt.Println("'microsoft'是有效的WFN值")
}
WFN匹配
Match
WFN匹配。
go
func (w *WFN) Match(other *WFN) bool
MatchWFN
WFN匹配函数。
go
func MatchWFN(wfn1, wfn2 *WFN) bool
CompareWFN
比较两个WFN。
go
func CompareWFN(wfn1, wfn2 *WFN) int
示例:
go
// 创建匹配模式
pattern := &cpe.WFN{
Part: "a",
Vendor: "microsoft",
Product: cpe.WFNAny, // 任意产品
Version: cpe.WFNAny, // 任意版本
}
// 测试目标
targets := []*cpe.WFN{
{Part: "a", Vendor: "microsoft", Product: "windows", Version: "10"},
{Part: "a", Vendor: "microsoft", Product: "office", Version: "2019"},
{Part: "a", Vendor: "oracle", Product: "java", Version: "11"},
}
fmt.Printf("模式: %s\n", pattern.String())
fmt.Println("匹配结果:")
for i, target := range targets {
match := pattern.Match(target)
status := "❌"
if match {
status = "✅"
}
fmt.Printf(" %s 目标%d: %s\n", status, i+1, target.String())
}
WFN规范化
Normalize
规范化WFN。
go
func (w *WFN) Normalize() *WFN
NormalizeWFN
规范化WFN对象。
go
func NormalizeWFN(wfn *WFN) *WFN
NormalizeWFNValue
规范化WFN值。
go
func NormalizeWFNValue(value string) string
示例:
go
// 创建需要规范化的WFN
unnormalized := &cpe.WFN{
Part: "A", // 应该是小写
Vendor: "Microsoft", // 应该是小写
Product: "Windows~10", // 特殊字符需要转义
Version: "10.0.19041.1234",
}
fmt.Printf("规范化前: %s\n", unnormalized.String())
// 规范化
normalized := unnormalized.Normalize()
fmt.Printf("规范化后: %s\n", normalized.String())
// 规范化单个值
value := "Product~Name"
normalizedValue := cpe.NormalizeWFNValue(value)
fmt.Printf("值规范化: %s -> %s\n", value, normalizedValue)
WFN转义
QuoteWFNValue
转义WFN值中的特殊字符。
go
func QuoteWFNValue(value string) string
UnquoteWFNValue
反转义WFN值。
go
func UnquoteWFNValue(value string) string
EscapeWFNValue
转义WFN值。
go
func EscapeWFNValue(value string) string
示例:
go
// 包含特殊字符的值
specialValue := "product~name*with?chars"
// 转义
quoted := cpe.QuoteWFNValue(specialValue)
fmt.Printf("原始值: %s\n", specialValue)
fmt.Printf("转义后: %s\n", quoted)
// 反转义
unquoted := cpe.UnquoteWFNValue(quoted)
fmt.Printf("反转义: %s\n", unquoted)
// 验证往返转换
if specialValue == unquoted {
fmt.Println("✅ 往返转换成功")
} else {
fmt.Println("❌ 往返转换失败")
}
WFN集合操作
WFNSet
WFN集合类型。
go
type WFNSet struct {
items map[string]*WFN
mutex sync.RWMutex
}
NewWFNSet
创建新的WFN集合。
go
func NewWFNSet() *WFNSet
WFN集合方法
go
// 添加WFN
func (s *WFNSet) Add(wfn *WFN) bool
// 移除WFN
func (s *WFNSet) Remove(wfn *WFN) bool
// 检查是否包含
func (s *WFNSet) Contains(wfn *WFN) bool
// 获取大小
func (s *WFNSet) Size() int
// 转换为切片
func (s *WFNSet) ToSlice() []*WFN
示例:
go
// 创建WFN集合
wfnSet := cpe.NewWFNSet()
// 添加WFN
wfn1 := &cpe.WFN{Part: "a", Vendor: "microsoft", Product: "windows"}
wfn2 := &cpe.WFN{Part: "a", Vendor: "apache", Product: "tomcat"}
wfnSet.Add(wfn1)
wfnSet.Add(wfn2)
fmt.Printf("集合大小: %d\n", wfnSet.Size())
// 检查包含
if wfnSet.Contains(wfn1) {
fmt.Println("集合包含Windows WFN")
}
// 转换为切片
wfnSlice := wfnSet.ToSlice()
fmt.Printf("集合内容:\n")
for i, wfn := range wfnSlice {
fmt.Printf(" %d. %s\n", i+1, wfn.String())
}
完整示例
go
package main
import (
"fmt"
"log"
"github.com/scagogogo/cpe"
)
func main() {
fmt.Println("=== WFN格式示例 ===")
// 示例1:CPE到WFN转换
fmt.Println("\n1. CPE到WFN转换:")
cpeStrings := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*",
"cpe:/a:oracle:java:11.0.12",
}
for i, cpeStr := range cpeStrings {
fmt.Printf("\n示例 %d: %s\n", i+1, cpeStr)
cpeObj, err := cpe.ParseCPE(cpeStr)
if err != nil {
log.Printf("解析失败: %v", err)
continue
}
wfn, err := cpe.CPEToWFN(cpeObj)
if err != nil {
log.Printf("转换失败: %v", err)
continue
}
fmt.Printf(" WFN: %s\n", wfn.String())
fmt.Printf(" 部件: %s\n", wfn.Part)
fmt.Printf(" 供应商: %s\n", wfn.Vendor)
fmt.Printf(" 产品: %s\n", wfn.Product)
fmt.Printf(" 版本: %s\n", wfn.Version)
}
// 示例2:WFN到CPE转换
fmt.Println("\n2. WFN到CPE转换:")
wfn := &cpe.WFN{
Part: "a",
Vendor: "adobe",
Product: "reader",
Version: "2021.001.20150",
Update: cpe.WFNAny,
Edition: cpe.WFNAny,
}
fmt.Printf("WFN: %s\n", wfn.String())
cpe23, err := cpe.WFNToCPE23(wfn)
if err != nil {
log.Printf("转换为CPE 2.3失败: %v", err)
} else {
fmt.Printf("CPE 2.3: %s\n", cpe23)
}
cpe22, err := cpe.WFNToCPE22(wfn)
if err != nil {
log.Printf("转换为CPE 2.2失败: %v", err)
} else {
fmt.Printf("CPE 2.2: %s\n", cpe22)
}
// 示例3:WFN匹配
fmt.Println("\n3. WFN匹配:")
pattern := &cpe.WFN{
Part: "a",
Vendor: "microsoft",
Product: cpe.WFNAny,
Version: cpe.WFNAny,
}
targets := []*cpe.WFN{
{Part: "a", Vendor: "microsoft", Product: "windows", Version: "10"},
{Part: "a", Vendor: "microsoft", Product: "office", Version: "2019"},
{Part: "a", Vendor: "oracle", Product: "java", Version: "11"},
{Part: "o", Vendor: "microsoft", Product: "windows", Version: "10"},
}
fmt.Printf("匹配模式: %s\n", pattern.String())
fmt.Println("匹配结果:")
for i, target := range targets {
match := pattern.Match(target)
status := "❌"
if match {
status = "✅"
}
fmt.Printf(" %s 目标%d: %s\n", status, i+1, target.String())
}
// 示例4:WFN验证
fmt.Println("\n4. WFN验证:")
testWFNs := []*cpe.WFN{
{Part: "a", Vendor: "microsoft", Product: "windows"}, // 有效
{Part: "x", Vendor: "microsoft", Product: "windows"}, // 无效部件
{Part: "a", Vendor: "", Product: "windows"}, // 空供应商
{Part: "a", Vendor: "microsoft", Product: ""}, // 空产品
}
for i, testWFN := range testWFNs {
err := testWFN.Validate()
status := "✅"
if err != nil {
status = "❌"
}
fmt.Printf(" %s 测试%d: %s\n", status, i+1, testWFN.String())
if err != nil {
fmt.Printf(" 错误: %v\n", err)
}
}
// 示例5:WFN规范化
fmt.Println("\n5. WFN规范化:")
unnormalized := &cpe.WFN{
Part: "A",
Vendor: "Microsoft",
Product: "Windows~10",
Version: "10.0.19041.1234",
}
fmt.Printf("规范化前: %s\n", unnormalized.String())
normalized := unnormalized.Normalize()
fmt.Printf("规范化后: %s\n", normalized.String())
// 示例6:特殊字符处理
fmt.Println("\n6. 特殊字符处理:")
specialValues := []string{
"product~name",
"version*with?wildcards",
"name:with:colons",
"path\\with\\backslashes",
}
for _, value := range specialValues {
quoted := cpe.QuoteWFNValue(value)
unquoted := cpe.UnquoteWFNValue(quoted)
fmt.Printf(" 原始: %s\n", value)
fmt.Printf(" 转义: %s\n", quoted)
fmt.Printf(" 还原: %s\n", unquoted)
fmt.Printf(" 正确: %t\n\n", value == unquoted)
}
}