WFN (Well-Formed Name)
The CPE library provides comprehensive support for Well-Formed Names (WFN), which are the canonical internal representation of CPE names as defined in the CPE specification.
WFN Structure
WFN
type WFN struct {
Part string // Component type
Vendor string // Vendor name
Product string // Product name
Version string // Version
Update string // Update
Edition string // Edition
Language string // Language
SoftwareEdition string // Software edition
TargetSoftware string // Target software
TargetHardware string // Target hardware
Other string // Other attributes
}The WFN structure represents the canonical form of a CPE name with all attributes properly normalized.
Creating WFN Objects
FromCPE
func FromCPE(cpe *CPE) *WFNCreates a WFN from a CPE object.
Parameters:
cpe- CPE object to convert
Returns:
*WFN- WFN representation
Example:
// Create CPE and convert to WFN
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
wfn := cpe.FromCPE(cpeObj)
fmt.Printf("WFN Part: %s\n", wfn.Part)
fmt.Printf("WFN Vendor: %s\n", wfn.Vendor)
fmt.Printf("WFN Product: %s\n", wfn.Product)
fmt.Printf("WFN Version: %s\n", wfn.Version)FromCPE23String
func FromCPE23String(cpe23 string) (*WFN, error)Creates a WFN directly from a CPE 2.3 format string.
Parameters:
cpe23- CPE 2.3 format string
Returns:
*WFN- WFN objecterror- Error if parsing fails
Example:
wfn, err := cpe.FromCPE23String("cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Vendor: %s, Product: %s, Version: %s\n",
wfn.Vendor, wfn.Product, wfn.Version)FromCPE22String
func FromCPE22String(cpe22 string) (*WFN, error)Creates a WFN from a CPE 2.2 format string.
Parameters:
cpe22- CPE 2.2 format string
Returns:
*WFN- WFN objecterror- Error if parsing fails
Example:
wfn, err := cpe.FromCPE22String("cpe:/a:apache:tomcat:8.5.0")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Converted CPE 2.2 to WFN: %s %s %s\n",
wfn.Vendor, wfn.Product, wfn.Version)Converting from WFN
ToCPE
func (w *WFN) ToCPE() *CPEConverts a WFN to a CPE object.
Returns:
*CPE- CPE object representation
Example:
// Create WFN and convert to CPE
wfn := &cpe.WFN{
Part: "a",
Vendor: "microsoft",
Product: "windows",
Version: "10",
}
cpeObj := wfn.ToCPE()
fmt.Printf("CPE URI: %s\n", cpeObj.GetURI())ToCPE23String
func (w *WFN) ToCPE23String() stringConverts a WFN to CPE 2.3 format string.
Returns:
string- CPE 2.3 format string
Example:
wfn := &cpe.WFN{
Part: "a",
Vendor: "apache",
Product: "tomcat",
Version: "9.0.0",
}
cpe23 := wfn.ToCPE23String()
fmt.Printf("CPE 2.3: %s\n", cpe23)
// Output: cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*ToCPE22String
func (w *WFN) ToCPE22String() stringConverts a WFN to CPE 2.2 format string.
Returns:
string- CPE 2.2 format string
Example:
wfn := &cpe.WFN{
Part: "a",
Vendor: "apache",
Product: "tomcat",
Version: "8.5.0",
}
cpe22 := wfn.ToCPE22String()
fmt.Printf("CPE 2.2: %s\n", cpe22)
// Output: cpe:/a:apache:tomcat:8.5.0WFN Matching
WFNMatch
func WFNMatch(wfn1, wfn2 *WFN) boolPerforms WFN-level matching between two WFN objects.
Parameters:
wfn1- First WFN to comparewfn2- Second WFN to compare
Returns:
bool-trueif WFNs match,falseotherwise
Example:
wfn1, _ := cpe.FromCPE23String("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
wfn2, _ := cpe.FromCPE23String("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*")
if cpe.WFNMatch(wfn2, wfn1) {
fmt.Println("WFNs match")
}Match
func (w *WFN) Match(other *WFN) boolInstance method for WFN matching.
Parameters:
other- WFN to match against
Returns:
bool-trueif WFNs match,falseotherwise
Example:
pattern, _ := cpe.FromCPE23String("cpe:2.3:a:*:*:*:*:*:*:*:*:*:*")
target, _ := cpe.FromCPE23String("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
if pattern.Match(target) {
fmt.Println("Target matches pattern")
}Value Handling
WFN uses special value handling for logical values:
Special Values
ANY(*) - Matches any valueNA(-) - Not applicable/undefined
FSStringToURI
func FSStringToURI(fs string) stringConverts a formatted string to URI format.
Parameters:
fs- Formatted string value
Returns:
string- URI-encoded value
URIToFSString
func URIToFSString(uri string) stringConverts a URI-encoded value to formatted string.
Parameters:
uri- URI-encoded value
Returns:
string- Formatted string value
Escape Handling
EscapeValue
func EscapeValue(value string) stringEscapes special characters in a value for WFN representation.
Parameters:
value- Value to escape
Returns:
string- Escaped value
Example:
escaped := cpe.EscapeValue("product:name")
fmt.Printf("Escaped: %s\n", escaped) // product\:nameUnescapeValue
func UnescapeValue(value string) stringUnescapes a WFN value to its original form.
Parameters:
value- Escaped value
Returns:
string- Unescaped value
Example:
unescaped := cpe.UnescapeValue("product\\:name")
fmt.Printf("Unescaped: %s\n", unescaped) // product:nameWFN Validation
ValidateWFN
func ValidateWFN(wfn *WFN) errorValidates a WFN object for correctness.
Parameters:
wfn- WFN to validate
Returns:
error- Error if validation fails
Example:
wfn := &cpe.WFN{
Part: "a",
Vendor: "apache",
Product: "tomcat",
Version: "9.0.0",
}
err := cpe.ValidateWFN(wfn)
if err != nil {
log.Printf("WFN validation failed: %v", err)
} else {
fmt.Println("WFN is valid")
}WFN Normalization
NormalizeWFN
func NormalizeWFN(wfn *WFN) *WFNNormalizes a WFN by applying standard transformations.
Parameters:
wfn- WFN to normalize
Returns:
*WFN- Normalized WFN
Example:
wfn := &cpe.WFN{
Part: "A", // Will be normalized to "a"
Vendor: "Apache", // Will be normalized to "apache"
Product: "Tomcat", // Will be normalized to "tomcat"
Version: "9.0.0",
}
normalized := cpe.NormalizeWFN(wfn)
fmt.Printf("Normalized vendor: %s\n", normalized.Vendor) // apacheComplete Example
package main
import (
"fmt"
"log"
"github.com/scagogogo/cpe"
)
func main() {
// Create WFN from CPE 2.3 string
fmt.Println("=== Creating WFN from CPE 2.3 ===")
wfn1, err := cpe.FromCPE23String("cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Part: %s\n", wfn1.Part)
fmt.Printf("Vendor: %s\n", wfn1.Vendor)
fmt.Printf("Product: %s\n", wfn1.Product)
fmt.Printf("Version: %s\n", wfn1.Version)
// Create WFN from CPE 2.2 string
fmt.Println("\n=== Creating WFN from CPE 2.2 ===")
wfn2, err := cpe.FromCPE22String("cpe:/a:microsoft:windows:10")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Vendor: %s\n", wfn2.Vendor)
fmt.Printf("Product: %s\n", wfn2.Product)
fmt.Printf("Version: %s\n", wfn2.Version)
// Convert WFN back to different formats
fmt.Println("\n=== Converting WFN to different formats ===")
cpe23 := wfn1.ToCPE23String()
cpe22 := wfn1.ToCPE22String()
fmt.Printf("CPE 2.3: %s\n", cpe23)
fmt.Printf("CPE 2.2: %s\n", cpe22)
// Convert to CPE object
cpeObj := wfn1.ToCPE()
fmt.Printf("CPE URI: %s\n", cpeObj.GetURI())
// WFN matching
fmt.Println("\n=== WFN Matching ===")
pattern, _ := cpe.FromCPE23String("cpe:2.3:a:apache:*:*:*:*:*:*:*:*:*")
target, _ := cpe.FromCPE23String("cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*")
if pattern.Match(target) {
fmt.Println("Target matches pattern")
} else {
fmt.Println("Target does not match pattern")
}
// Create WFN manually
fmt.Println("\n=== Creating WFN manually ===")
manualWFN := &cpe.WFN{
Part: "a",
Vendor: "oracle",
Product: "java",
Version: "11.0.12",
}
// Validate WFN
err = cpe.ValidateWFN(manualWFN)
if err != nil {
log.Printf("WFN validation failed: %v", err)
} else {
fmt.Println("Manual WFN is valid")
}
// Convert manual WFN to CPE
manualCPE := manualWFN.ToCPE()
fmt.Printf("Manual WFN as CPE: %s\n", manualCPE.GetURI())
// Demonstrate escape handling
fmt.Println("\n=== Escape Handling ===")
specialValue := "product:with:colons"
escaped := cpe.EscapeValue(specialValue)
unescaped := cpe.UnescapeValue(escaped)
fmt.Printf("Original: %s\n", specialValue)
fmt.Printf("Escaped: %s\n", escaped)
fmt.Printf("Unescaped: %s\n", unescaped)
// WFN normalization
fmt.Println("\n=== WFN Normalization ===")
unnormalizedWFN := &cpe.WFN{
Part: "A",
Vendor: "APACHE",
Product: "TOMCAT",
Version: "9.0.0",
}
normalizedWFN := cpe.NormalizeWFN(unnormalizedWFN)
fmt.Printf("Original vendor: %s\n", unnormalizedWFN.Vendor)
fmt.Printf("Normalized vendor: %s\n", normalizedWFN.Vendor)
}