1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
package cpe
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
// CPE 2.3 binding.
type V23Binding struct {
Part Part // Part attribute (NISTIR7695 5.3.3.1).
Vendor AvString // Vendor attribute (NISTIR7695 5.3.3.2).
Product AvString // Product attribute (NISTIR7695 5.3.3.3).
Version AvString // Version attribute (NISTIR7695 5.3.3.4).
Update AvString // Update attribute (NISTIR7695 5.3.3.5).
Edition AvString // Edition attribute (NISTIR7695 5.3.3.6).
SwEdition AvString // Software edition attribute (NISTIR7695 5.3.3.7).
TargetSw AvString // Target software attribute (NISTIR7695 5.3.3.8).
TargetHw AvString // Target hardware attribute (NISTIR7695 5.3.3.9).
Lang AvString // Language attribute (NISTIR7695 5.3.3.10).
Other AvString // Other attribute (NISTIR7695 5.3.3.11).
}
// formatted string prefix
var cpe23Prefix = "cpe:2.3:"
// missing prefix error
var missingPrefix = errors.New("missing CPE 2.3 prefix")
// Create binding from CPE 2.3 formatted string.
func NewV23Binding(s string) (V23Binding, error) {
// check prefix
if s[0:len(cpe23Prefix)] != cpe23Prefix {
return V23Binding{}, missingPrefix
}
// tokenize string, check for error
toks, err := tokenize([]byte(s[len(cpe23Prefix):]))
if err != nil {
return V23Binding{}, err
}
// check token count
if len(toks) != 11 {
err = fmt.Errorf("invalid attribute count: %d != 11", len(toks))
return V23Binding{}, err
}
// create part
part, err := newPart(toks[0])
if err != nil {
return V23Binding{}, err
}
// parse tokens into strings
strs := make([]AvString, len(toks) - 1)
for i, t := range(toks[1:]) {
if strs[i], err = newAvString(t); err != nil {
return V23Binding{}, err
}
}
// build and return result
return V23Binding {
Part: part,
Vendor: strs[0],
Product: strs[1],
Version: strs[2],
Update: strs[3],
Edition: strs[4],
Lang: strs[5],
SwEdition: strs[6],
TargetSw: strs[7],
TargetHw: strs[8],
Other: strs[9],
}, nil
}
// Serialize CPE 2.3 binding as formatted string.
func (v V23Binding) String() string {
return cpe23Prefix + strings.Join([]string {
v.Part.String(),
v.Vendor.String(),
v.Product.String(),
v.Version.String(),
v.Update.String(),
v.Edition.String(),
v.Lang.String(),
v.SwEdition.String(),
v.TargetSw.String(),
v.TargetHw.String(),
v.Other.String(),
}, ":")
}
// Unmarshal CPE 2.3 binding from JSON string.
func (me *V23Binding) UnmarshalJSON(b []byte) error {
// decode json string
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
// create binding
binding, err := NewV23Binding(s)
if err != nil {
return err
}
// save result, return success
*me = binding
return nil
}
// Marshal CPE binding as JSON string.
func (v V23Binding) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
|