1package main
2
3import (
4	"bytes"
5	"compress/gzip"
6	"encoding/xml"
7	"fmt"
8	"html/template"
9	"io/ioutil"
10	"math/rand"
11	"net/http"
12	"os"
13)
14
15// CpeList is CPE list
16type CpeList struct {
17	CpeItems []CpeItem `xml:"cpe-item"`
18}
19
20// CpeItem has CPE information
21type CpeItem struct {
22	Name      string    `xml:"name,attr"`
23	Cpe23Item Cpe23Item `xml:"cpe23-item"`
24}
25
26// Cpe23Item has CPE 2.3 information
27type Cpe23Item struct {
28	Name string `xml:"name,attr"`
29}
30
31// Pair has fs and uri
32type Pair struct {
33	URI string
34	FS  string
35}
36
37func main() {
38	url := "http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz"
39	resp, err := http.Get(url)
40	if err != nil || resp.StatusCode != 200 {
41		fmt.Printf("HTTP error. errs: %s, url: %s", err, url)
42		return
43	}
44
45	body, _ := ioutil.ReadAll(resp.Body)
46	defer resp.Body.Close()
47
48	b := bytes.NewBufferString(string(body))
49	reader, err := gzip.NewReader(b)
50	defer reader.Close()
51	if err != nil {
52		fmt.Printf("Failed to decompress NVD feedfile. url: %s, err: %s", url, err)
53		return
54	}
55	bytes, err := ioutil.ReadAll(reader)
56	if err != nil {
57		fmt.Printf("Failed to Read NVD feedfile. url: %s, err: %s", url, err)
58		return
59	}
60	cpeList := CpeList{}
61	if err = xml.Unmarshal(bytes, &cpeList); err != nil {
62		fmt.Printf("Failed to unmarshal. url: %s, err: %s", url, err)
63		return
64	}
65
66	var uriList, fsList []string
67	for _, cpeItem := range cpeList.CpeItems {
68		uriList = append(uriList, cpeItem.Name)
69		fsList = append(fsList, cpeItem.Cpe23Item.Name)
70	}
71	shuffle(fsList)
72
73	pair := []Pair{}
74	for i, uri := range uriList {
75		pair = append(pair, Pair{
76			URI: uri,
77			FS:  fsList[i],
78		})
79	}
80	fmt.Printf("%d data...\n", len(cpeList.CpeItems))
81
82	fmt.Println("Generating test code...")
83	t := template.Must(template.ParseFiles("dictionary_test.tmpl"))
84	file, _ := os.Create(`./dictionary_test.go`)
85	defer file.Close()
86	t.Execute(file, map[string]interface{}{
87		"Pair": pair,
88	})
89}
90
91func shuffle(data []string) {
92	n := len(data)
93	for i := n - 1; i >= 0; i-- {
94		j := rand.Intn(i + 1)
95		data[i], data[j] = data[j], data[i]
96	}
97}
98