解析功能
本页面描述了CPE库中用于解析CPE字符串的函数和方法,包括CPE 2.2和2.3格式的解析功能。
主要解析函数
ParseCpe23
解析CPE 2.3格式字符串。
go
func ParseCpe23(cpe23 string) (*CPE, error)
参数:
cpe23
: CPE 2.3格式字符串
返回值:
*CPE
: 解析后的CPE对象error
: 解析错误(如果有)
示例:
go
cpeObj, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
log.Fatal(err)
}
fmt.Printf("供应商: %s, 产品: %s\n", cpeObj.Vendor, cpeObj.ProductName)
ParseCpe22
解析CPE 2.2格式字符串。
go
func ParseCpe22(cpe22 string) (*CPE, error)
参数:
cpe22
: CPE 2.2格式字符串
返回值:
*CPE
: 解析后的CPE对象error
: 解析错误(如果有)
示例:
go
cpeObj, err := cpe.ParseCpe22("cpe:/a:apache:tomcat:9.0.0")
if err != nil {
log.Fatal(err)
}
fmt.Printf("产品: %s, 版本: %s\n", cpeObj.ProductName, cpeObj.Version)
ParseCPE
通用CPE解析函数,自动检测格式。
go
func ParseCPE(cpeString string) (*CPE, error)
参数:
cpeString
: CPE字符串(2.2或2.3格式)
返回值:
*CPE
: 解析后的CPE对象error
: 解析错误(如果有)
示例:
go
// 自动检测格式
cpe23, _ := cpe.ParseCPE("cpe:2.3:a:oracle:java:11.0.12:*:*:*:*:*:*:*")
cpe22, _ := cpe.ParseCPE("cpe:/a:oracle:java:11.0.12")
fmt.Printf("两个CPE是否相同: %t\n", cpe23.Match(cpe22))
批量解析函数
ParseCPEList
批量解析CPE字符串列表。
go
func ParseCPEList(cpeStrings []string) ([]*CPE, []error)
参数:
cpeStrings
: CPE字符串列表
返回值:
[]*CPE
: 成功解析的CPE对象列表[]error
: 解析错误列表
示例:
go
cpeStrings := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:/a:apache:tomcat:9.0.0",
"invalid-cpe-string",
}
cpes, errors := cpe.ParseCPEList(cpeStrings)
fmt.Printf("成功解析: %d, 错误: %d\n", len(cpes), len(errors))
ParseCPEFromFile
从文件中解析CPE字符串。
go
func ParseCPEFromFile(filename string) ([]*CPE, error)
参数:
filename
: 包含CPE字符串的文件路径
返回值:
[]*CPE
: 解析后的CPE对象列表error
: 文件读取或解析错误
示例:
go
cpes, err := cpe.ParseCPEFromFile("cpe_list.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("从文件解析了 %d 个CPE\n", len(cpes))
解析选项
ParseOptions
解析选项配置。
go
type ParseOptions struct {
StrictMode bool // 严格模式
AllowEmpty bool // 允许空字段
NormalizeCase bool // 规范化大小写
ValidateFormat bool // 验证格式
IgnoreErrors bool // 忽略非致命错误
}
ParseWithOptions
使用自定义选项解析CPE。
go
func ParseWithOptions(cpeString string, options *ParseOptions) (*CPE, error)
示例:
go
options := &cpe.ParseOptions{
StrictMode: true,
NormalizeCase: true,
ValidateFormat: true,
}
cpeObj, err := cpe.ParseWithOptions(cpeString, options)
if err != nil {
log.Printf("严格模式解析失败: %v", err)
}
格式验证
ValidateCPEFormat
验证CPE字符串格式。
go
func ValidateCPEFormat(cpeString string) error
参数:
cpeString
: 要验证的CPE字符串
返回值:
error
: 验证错误(如果格式无效)
示例:
go
err := cpe.ValidateCPEFormat("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
fmt.Printf("格式无效: %v\n", err)
} else {
fmt.Println("格式有效")
}
IsCPE23Format
检查字符串是否为CPE 2.3格式。
go
func IsCPE23Format(cpeString string) bool
IsCPE22Format
检查字符串是否为CPE 2.2格式。
go
func IsCPE22Format(cpeString string) bool
示例:
go
cpeString := "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
if cpe.IsCPE23Format(cpeString) {
fmt.Println("这是CPE 2.3格式")
} else if cpe.IsCPE22Format(cpeString) {
fmt.Println("这是CPE 2.2格式")
} else {
fmt.Println("未知格式")
}
组件解析
ParsePart
解析组件类型。
go
func ParsePart(partString string) (Part, error)
示例:
go
part, err := cpe.ParsePart("a")
if err != nil {
log.Fatal(err)
}
fmt.Printf("组件类型: %s (%s)\n", part.ShortName, part.LongName)
ParseVendor
解析供应商信息。
go
func ParseVendor(vendorString string) (Vendor, error)
ParseProduct
解析产品信息。
go
func ParseProduct(productString string) (Product, error)
ParseVersion
解析版本信息。
go
func ParseVersion(versionString string) (Version, error)
特殊值处理
通配符处理
CPE解析器能够正确处理特殊值:
*
(星号): 表示"任意值"-
(连字符): 表示"不适用"
go
// 解析包含通配符的CPE
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:*:*:*:*:*:*:*:*:*")
fmt.Printf("产品: %s\n", cpeObj.ProductName) // 输出: *
转义字符处理
解析器能够处理CPE中的转义字符:
go
// 包含特殊字符的CPE
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:vendor:product\\~name:1.0:*:*:*:*:*:*:*")
fmt.Printf("产品: %s\n", cpeObj.ProductName) // 输出: product~name
错误处理
解析错误类型
解析过程中可能遇到的错误类型:
go
const (
ErrorInvalidFormat = "无效的CPE格式"
ErrorInvalidPart = "无效的组件类型"
ErrorInvalidVendor = "无效的供应商"
ErrorInvalidProduct = "无效的产品名称"
ErrorInvalidVersion = "无效的版本信息"
ErrorTooFewComponents = "组件数量不足"
ErrorTooManyComponents = "组件数量过多"
)
错误检查函数
go
// 检查是否为格式错误
func IsFormatError(err error) bool
// 检查是否为组件错误
func IsComponentError(err error) bool
// 检查是否为验证错误
func IsValidationError(err error) bool
示例:
go
_, err := cpe.ParseCpe23("invalid-cpe")
if cpe.IsFormatError(err) {
fmt.Println("这是一个格式错误")
}
性能优化
解析缓存
对于频繁解析的CPE字符串,可以使用缓存:
go
// 启用解析缓存
cpe.EnableParseCache(1000) // 缓存1000个解析结果
// 解析CPE(会被缓存)
cpeObj1, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpeObj2, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*") // 从缓存获取
// 清除缓存
cpe.ClearParseCache()
批量解析优化
go
// 并行解析大量CPE
func ParseCPEListParallel(cpeStrings []string, workers int) ([]*CPE, []error)
完整示例
go
package main
import (
"fmt"
"log"
"github.com/scagogogo/cpe"
)
func main() {
// 基本解析示例
fmt.Println("=== 基本解析示例 ===")
// 解析CPE 2.3
cpe23, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
log.Fatal(err)
}
fmt.Printf("CPE 2.3解析结果:\n")
fmt.Printf(" 组件类型: %s\n", cpe23.Part.LongName)
fmt.Printf(" 供应商: %s\n", cpe23.Vendor)
fmt.Printf(" 产品: %s\n", cpe23.ProductName)
fmt.Printf(" 版本: %s\n", cpe23.Version)
// 解析CPE 2.2
cpe22, err := cpe.ParseCpe22("cpe:/a:apache:tomcat:9.0.0")
if err != nil {
log.Fatal(err)
}
fmt.Printf("\nCPE 2.2解析结果:\n")
fmt.Printf(" 供应商: %s\n", cpe22.Vendor)
fmt.Printf(" 产品: %s\n", cpe22.ProductName)
fmt.Printf(" 版本: %s\n", cpe22.Version)
// 批量解析示例
fmt.Println("\n=== 批量解析示例 ===")
cpeStrings := []string{
"cpe:2.3:a:oracle:java:11.0.12:*:*:*:*:*:*:*",
"cpe:/a:nginx:nginx:1.18.0",
"cpe:2.3:o:canonical:ubuntu:20.04:*:*:*:*:*:*:*",
"invalid-cpe-format", // 这个会产生错误
}
cpes, errors := cpe.ParseCPEList(cpeStrings)
fmt.Printf("成功解析: %d 个CPE\n", len(cpes))
fmt.Printf("解析错误: %d 个\n", len(errors))
for i, cpeObj := range cpes {
fmt.Printf(" %d. %s %s %s\n", i+1, cpeObj.Vendor, cpeObj.ProductName, cpeObj.Version)
}
for i, err := range errors {
fmt.Printf(" 错误 %d: %v\n", i+1, err)
}
// 格式验证示例
fmt.Println("\n=== 格式验证示例 ===")
testStrings := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:/a:apache:tomcat:9.0.0",
"invalid-format",
"cpe:2.3:x:vendor:product:1.0:*:*:*:*:*:*:*", // 无效的组件类型
}
for _, testStr := range testStrings {
err := cpe.ValidateCPEFormat(testStr)
if err != nil {
fmt.Printf("❌ %s - %v\n", testStr, err)
} else {
fmt.Printf("✅ %s - 格式有效\n", testStr)
}
}
}