Skip to content

Commit 9ce0594

Browse files
committed
docs: 为WFN模块添加详细的中文注释
1. 为WFN结构体及其字段添加详细说明 2. 为所有方法添加完整的中文注释,包括方法功能描述 3. 添加所有方法的输入参数和返回值说明 4. 为每个方法提供多个使用示例代码 5. 增加特殊情况和注意事项说明 6. 完善规则解释和转义机制描述
1 parent c530a9f commit 9ce0594

File tree

1 file changed

+285
-11
lines changed

1 file changed

+285
-11
lines changed

wfn.go

Lines changed: 285 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,45 @@ import (
77
)
88

99
// WFN (Well-Formed Name) 表示CPE的规范化内部表示
10+
// WFN是CPE的内部规范表示形式,用于存储CPE各个组成部分的值
11+
// 一个完整的WFN包含以下11个属性:part, vendor, product, version, update, edition, language,
12+
// softwareEdition, targetSoftware, targetHardware和other
1013
type WFN struct {
11-
Part string
12-
Vendor string
13-
Product string
14-
Version string
15-
Update string
16-
Edition string
17-
Language string
18-
SoftwareEdition string
19-
TargetSoftware string
20-
TargetHardware string
21-
Other string
14+
Part string // 组件类型: a(应用程序)、o(操作系统)、h(硬件设备)
15+
Vendor string // 厂商名称
16+
Product string // 产品名称
17+
Version string // 版本号
18+
Update string // 更新版本
19+
Edition string // 版本
20+
Language string // 语言
21+
SoftwareEdition string // 软件版本
22+
TargetSoftware string // 目标软件
23+
TargetHardware string // 目标硬件
24+
Other string // 其他信息
2225
}
2326

2427
// FromCPE 从CPE结构体创建WFN
28+
// 本方法将CPE结构体转换为规范化的WFN格式,用于内部处理和比较
29+
//
30+
// 参数:
31+
// - cpe: CPE结构体指针,包含各个属性的值
32+
//
33+
// 返回值:
34+
// - *WFN: 转换后的WFN结构体指针
35+
//
36+
// 示例:
37+
//
38+
// cpe := &CPE{
39+
// Part: *PartApplication,
40+
// Vendor: "microsoft",
41+
// ProductName: "windows",
42+
// Version: "10",
43+
// }
44+
// wfn := FromCPE(cpe)
45+
// fmt.Println(wfn.Part) // 输出: "a"
46+
// fmt.Println(wfn.Vendor) // 输出: "microsoft"
47+
// fmt.Println(wfn.Product) // 输出: "windows"
48+
// fmt.Println(wfn.Version) // 输出: "10"
2549
func FromCPE(cpe *CPE) *WFN {
2650
return &WFN{
2751
Part: cpe.Part.ShortName,
@@ -39,6 +63,27 @@ func FromCPE(cpe *CPE) *WFN {
3963
}
4064

4165
// ToCPE 转换WFN为CPE结构体
66+
// 本方法将WFN转换回CPE结构体,用于外部使用和展示
67+
//
68+
// 返回值:
69+
// - *CPE: 转换后的CPE结构体指针,包含从WFN提取的所有属性值
70+
//
71+
// 示例:
72+
//
73+
// wfn := &WFN{
74+
// Part: "a",
75+
// Vendor: "microsoft",
76+
// Product: "windows",
77+
// Version: "10",
78+
// }
79+
// cpe := wfn.ToCPE()
80+
// fmt.Println(cpe.Part.Name) // 输出: "Application"
81+
// fmt.Println(string(cpe.Vendor)) // 输出: "microsoft"
82+
// fmt.Println(cpe.Cpe23) // 输出CPE 2.3格式字符串
83+
//
84+
// 注意:
85+
// - 方法会自动设置CPE.Cpe23字段,生成CPE 2.3格式字符串
86+
// - 如果WFN.Part不是有效值(a/h/o),默认为应用程序(a)
4287
func (w *WFN) ToCPE() *CPE {
4388
cpe := &CPE{
4489
Vendor: Vendor(w.Vendor),
@@ -72,6 +117,32 @@ func (w *WFN) ToCPE() *CPE {
72117
}
73118

74119
// FromCPE23String 从CPE 2.3格式字符串创建WFN
120+
// 本方法解析CPE 2.3格式的字符串,将其转换为WFN结构体
121+
//
122+
// 参数:
123+
// - cpe23: 符合CPE 2.3规范的字符串,例如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
124+
//
125+
// 返回值:
126+
// - *WFN: 解析成功返回WFN结构体指针
127+
// - error: 解析失败返回错误信息
128+
//
129+
// 示例:
130+
//
131+
// wfn, err := FromCPE23String("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
132+
// if err != nil {
133+
// panic(err)
134+
// }
135+
// fmt.Println(wfn.Part) // 输出: "a"
136+
// fmt.Println(wfn.Vendor) // 输出: "microsoft"
137+
// fmt.Println(wfn.Product) // 输出: "windows"
138+
// fmt.Println(wfn.Version) // 输出: "10"
139+
//
140+
// 错误情况:
141+
// - 如果字符串不以"cpe:2.3:"开头,返回格式错误
142+
// - 如果字符串不包含13个部分(以冒号分隔),返回格式错误
143+
//
144+
// 注意:
145+
// - 方法会自动对每个字段进行反转义处理
75146
func FromCPE23String(cpe23 string) (*WFN, error) {
76147
// 移除cpe:2.3:前缀
77148
if !strings.HasPrefix(cpe23, "cpe:2.3:") {
@@ -101,13 +172,59 @@ func FromCPE23String(cpe23 string) (*WFN, error) {
101172
}
102173

103174
// FromCPE22String 从CPE 2.2格式字符串创建WFN
175+
// 本方法解析CPE 2.2格式的字符串,将其转换为WFN结构体
176+
// 内部实现是先将CPE 2.2转换为CPE 2.3格式,再调用FromCPE23String方法
177+
//
178+
// 参数:
179+
// - cpe22: 符合CPE 2.2规范的字符串,例如"cpe:/a:microsoft:windows:10"
180+
//
181+
// 返回值:
182+
// - *WFN: 解析成功返回WFN结构体指针
183+
// - error: 解析失败返回错误信息
184+
//
185+
// 示例:
186+
//
187+
// wfn, err := FromCPE22String("cpe:/a:microsoft:windows:10")
188+
// if err != nil {
189+
// panic(err)
190+
// }
191+
// fmt.Println(wfn.Part) // 输出: "a"
192+
// fmt.Println(wfn.Vendor) // 输出: "microsoft"
193+
// fmt.Println(wfn.Product) // 输出: "windows"
194+
// fmt.Println(wfn.Version) // 输出: "10"
195+
//
196+
// 错误情况:
197+
// - 如果转换后的CPE 2.3格式字符串无效,会返回FromCPE23String传递的错误
198+
//
199+
// 注意:
200+
// - 该方法依赖convertCpe22ToCpe23函数,该函数将CPE 2.2格式转换为CPE 2.3格式
104201
func FromCPE22String(cpe22 string) (*WFN, error) {
105202
// 转换成CPE 2.3格式,再解析
106203
cpe23 := convertCpe22ToCpe23(cpe22)
107204
return FromCPE23String(cpe23)
108205
}
109206

110207
// ToCPE23String 转换WFN为CPE 2.3格式字符串
208+
// 本方法将WFN结构体转换为标准的CPE 2.3格式字符串
209+
//
210+
// 返回值:
211+
// - string: 符合CPE 2.3规范的字符串,例如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
212+
//
213+
// 示例:
214+
//
215+
// wfn := &WFN{
216+
// Part: "a",
217+
// Vendor: "microsoft",
218+
// Product: "windows",
219+
// Version: "10",
220+
// }
221+
// cpe23 := wfn.ToCPE23String()
222+
// fmt.Println(cpe23) // 输出: "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
223+
//
224+
// 注意:
225+
// - 方法会自动对每个字段进行转义处理,使用escapeValue函数
226+
// - 所有字段之间用冒号(:)分隔,共有13部分
227+
// - 返回的字符串始终以"cpe:2.3:"开头
111228
func (w *WFN) ToCPE23String() string {
112229
parts := []string{
113230
"cpe", "2.3",
@@ -128,6 +245,31 @@ func (w *WFN) ToCPE23String() string {
128245
}
129246

130247
// ToCPE22String 转换WFN为CPE 2.2格式字符串
248+
// 本方法将WFN结构体转换为标准的CPE 2.2格式字符串
249+
//
250+
// 返回值:
251+
// - string: 符合CPE 2.2规范的字符串,例如"cpe:/a:microsoft:windows:10"
252+
//
253+
// 示例:
254+
//
255+
// wfn := &WFN{
256+
// Part: "a",
257+
// Vendor: "microsoft",
258+
// Product: "windows",
259+
// Version: "10",
260+
// Update: "sp1",
261+
// Edition: "pro",
262+
// Language: "zh-cn",
263+
// }
264+
// cpe22 := wfn.ToCPE22String()
265+
// fmt.Println(cpe22) // 输出: "cpe:/a:microsoft:windows:10:sp1:pro~zh-cn"
266+
//
267+
// 注意:
268+
// - CPE 2.2格式与CPE 2.3格式不完全兼容,部分字段可能无法完整表示
269+
// - 主要部分(Part, Vendor, Product, Version, Update)用冒号分隔
270+
// - 扩展属性(如Edition等)使用波浪线(~)分隔
271+
// - 方法会自动移除末尾空值的扩展属性
272+
// - 使用escapeValueForCpe22函数进行转义,转义规则与CPE 2.3不同
131273
func (w *WFN) ToCPE22String() string {
132274
cpePrefix := "cpe:/"
133275
mainParts := []string{
@@ -173,6 +315,31 @@ func (w *WFN) ToCPE22String() string {
173315
}
174316

175317
// escapeValue 对CPE 2.3格式的值进行转义
318+
// 本函数处理CPE 2.3格式中特殊字符的转义
319+
//
320+
// 参数:
321+
// - value: 需要转义的原始字符串值
322+
//
323+
// 返回值:
324+
// - string: 转义后的字符串
325+
//
326+
// 示例:
327+
//
328+
// escaped := escapeValue("windows.server")
329+
// fmt.Println(escaped) // 输出: "windows\.server"
330+
//
331+
// // 版本号中的点号不进行转义
332+
// escaped = escapeValue("2.0.1")
333+
// fmt.Println(escaped) // 输出: "2.0.1"
334+
//
335+
// 转义规则:
336+
// - 特殊值 "*"(ANY), "-"(NA) 和空字符串保持不变
337+
// - 点号(.)会被转义为"\.",除非出现在符合版本格式的字符串中
338+
// - 冒号(:)会被转义为"\:"
339+
//
340+
// 注意:
341+
// - 函数会识别版本号格式(如1.2.3),在这种情况下点号不做转义
342+
// - 这是为了保持版本号的可读性和一致性
176343
func escapeValue(value string) string {
177344
// 如果是特殊值或空值,不需要转义
178345
if value == "*" || value == "-" || value == "" {
@@ -202,6 +369,29 @@ func escapeValue(value string) string {
202369
}
203370

204371
// unescapeValue 对CPE 2.3格式的值进行反转义
372+
// 本函数处理CPE 2.3格式中特殊字符的反转义,是escapeValue的逆操作
373+
//
374+
// 参数:
375+
// - value: 需要反转义的字符串
376+
//
377+
// 返回值:
378+
// - string: 反转义后的原始字符串
379+
//
380+
// 示例:
381+
//
382+
// original := unescapeValue("windows\\.server")
383+
// fmt.Println(original) // 输出: "windows.server"
384+
//
385+
// original = unescapeValue("2\\.0\\.1")
386+
// fmt.Println(original) // 输出: "2.0.1"
387+
//
388+
// 反转义规则:
389+
// - 特殊值 "*"(ANY), "-"(NA) 和空字符串保持不变
390+
// - 所有形如"\x"的字符序列会被替换为"x",其中x可以是任何字符
391+
//
392+
// 注意:
393+
// - 使用正则表达式识别和替换所有转义序列
394+
// - 这个函数可以处理所有通过escapeValue函数转义的字符串
205395
func unescapeValue(value string) string {
206396
if value == "*" || value == "-" || value == "" {
207397
return value
@@ -213,6 +403,32 @@ func unescapeValue(value string) string {
213403
}
214404

215405
// escapeValueForCpe22 对CPE 2.2格式的值进行转义
406+
// 本函数处理CPE 2.2格式中特殊字符的转义,其规则与CPE 2.3不同
407+
//
408+
// 参数:
409+
// - value: 需要转义的原始字符串值
410+
//
411+
// 返回值:
412+
// - string: 转义后的字符串,符合CPE 2.2格式要求
413+
//
414+
// 示例:
415+
//
416+
// escaped := escapeValueForCpe22("windows/server")
417+
// fmt.Println(escaped) // 输出: "windows%2fserver"
418+
//
419+
// escaped = escapeValueForCpe22("demo:test")
420+
// fmt.Println(escaped) // 输出: "demo%3atest"
421+
//
422+
// 转义规则:
423+
// - 特殊值 "*"(ANY), "-"(NA) 和空字符串保持不变
424+
// - 反斜杠(\)转义为"\\"
425+
// - 冒号(:)转义为"%3a"
426+
// - 斜杠(/)转义为"%2f"
427+
// - 波浪线(~)转义为"%7e"
428+
//
429+
// 注意:
430+
// - CPE 2.2使用百分号编码(percent-encoding)来表示特殊字符,而不是反斜杠转义
431+
// - 这种格式更接近URI编码,使CPE更容易嵌入到URL中
216432
func escapeValueForCpe22(value string) string {
217433
if value == "*" || value == "-" || value == "" {
218434
return value
@@ -230,6 +446,39 @@ func escapeValueForCpe22(value string) string {
230446
}
231447

232448
// Match 比较两个WFN是否匹配
449+
// 本方法检查当前WFN与另一个WFN是否匹配,匹配规则遵循CPE规范
450+
//
451+
// 参数:
452+
// - other: 另一个WFN结构体指针,用于与当前WFN比较
453+
//
454+
// 返回值:
455+
// - bool: 如果匹配返回true,否则返回false
456+
//
457+
// 示例:
458+
//
459+
// wfn1 := &WFN{
460+
// Part: "a",
461+
// Vendor: "microsoft",
462+
// Product: "windows",
463+
// Version: "*", // 任意版本
464+
// }
465+
//
466+
// wfn2 := &WFN{
467+
// Part: "a",
468+
// Vendor: "microsoft",
469+
// Product: "windows",
470+
// Version: "10",
471+
// }
472+
//
473+
// fmt.Println(wfn1.Match(wfn2)) // 输出: true
474+
// fmt.Println(wfn2.Match(wfn1)) // 输出: true
475+
//
476+
// 匹配规则:
477+
// - 如果两个WFN的所有属性都匹配,则这两个WFN匹配
478+
// - 单个属性的匹配规则通过matchWFNAttribute函数定义
479+
// - 属性为"*"表示ANY,可以匹配任何值
480+
// - 如果两个属性都是"-"(NA),则它们匹配
481+
// - 其他情况要求精确匹配
233482
func (w *WFN) Match(other *WFN) bool {
234483
// 检查Part
235484
if !matchWFNAttribute(w.Part, other.Part) {
@@ -250,6 +499,31 @@ func (w *WFN) Match(other *WFN) bool {
250499
}
251500

252501
// matchWFNAttribute 匹配WFN的单个属性
502+
// 本函数检查两个WFN属性值是否匹配,遵循CPE规范的匹配规则
503+
//
504+
// 参数:
505+
// - a: 第一个属性值
506+
// - b: 第二个属性值
507+
//
508+
// 返回值:
509+
// - bool: 如果匹配返回true,否则返回false
510+
//
511+
// 示例:
512+
//
513+
// // ANY匹配任何值
514+
// fmt.Println(matchWFNAttribute("*", "windows")) // 输出: true
515+
//
516+
// // NA匹配NA
517+
// fmt.Println(matchWFNAttribute("-", "-")) // 输出: true
518+
//
519+
// // 精确匹配
520+
// fmt.Println(matchWFNAttribute("windows", "windows")) // 输出: true
521+
// fmt.Println(matchWFNAttribute("windows", "linux")) // 输出: false
522+
//
523+
// 匹配规则:
524+
// - 如果任一属性为"*"(ANY),则匹配
525+
// - 如果两个属性都是"-"(NA),则匹配
526+
// - 其他情况要求精确匹配(区分大小写)
253527
func matchWFNAttribute(a, b string) bool {
254528
// 如果有一个是ANY (*), 则匹配
255529
if a == "*" || b == "*" {

0 commit comments

Comments
 (0)