-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfile.go
138 lines (123 loc) · 3.34 KB
/
file.go
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package cvebaser
import (
"bytes"
"fmt"
"io"
"os"
"github.com/gohugoio/hugo/parser/pageparser"
"gopkg.in/yaml.v3"
)
// ParseCVEMDFile reads markdown file contents containing YAML and markdown
// and returns CVE data struct
func ParseCVEMDFile(reader io.Reader) (cve CVE, err error) {
pf, err := pageparser.ParseFrontMatterAndContent(reader)
if err != nil {
return cve, err
}
fm, err := yaml.Marshal(pf.FrontMatter)
if err != nil {
return cve, err
}
err = yaml.Unmarshal(fm, &cve)
if err != nil {
return cve, err
}
cve.Advisory = string(pf.Content)
return
}
// ParseResearcherMDFile reads markdown file contents containing YAML and markdown
// and returns Researcher data struct
func ParseResearcherMDFile(reader io.Reader) (researcher Researcher, err error) {
pf, err := pageparser.ParseFrontMatterAndContent(reader)
if err != nil {
return researcher, err
}
fm, err := yaml.Marshal(pf.FrontMatter)
if err != nil {
return researcher, err
}
err = yaml.Unmarshal(fm, &researcher)
if err != nil {
return researcher, err
}
researcher.Bio = string(pf.Content)
return
}
// ParseMDFile reads markdown file contents containing YAML and markdown
// and returns either CVE or Researcher data struct
func ParseMDFile(r io.Reader, tPtr interface{}) error {
pf, err := pageparser.ParseFrontMatterAndContent(r)
if err != nil {
return fmt.Errorf("error parsing front matter: %v", err)
}
fm, err := yaml.Marshal(pf.FrontMatter)
if err != nil {
return fmt.Errorf("error marshaling yaml: %v", err)
}
err = yaml.Unmarshal(fm, tPtr)
if err != nil {
return fmt.Errorf("erorr unmarshaling yaml: %v", err)
}
// Set field value for markdown text depending on CVE or Researcher
switch t := tPtr.(type) {
case *CVE:
t.Advisory = string(pf.Content)
case *Researcher:
t.Bio = string(pf.Content)
default:
return fmt.Errorf("unknown type: %+v", tPtr)
}
return nil
}
const yamlDelimLf = "---\n"
func CompileToFile(
f *os.File,
path string,
t interface{}, /* CVE or Researcher to marshal */
) error {
// Configure yaml encoding for custom indent spacing
var d bytes.Buffer
yamlEncoder := yaml.NewEncoder(&d)
// go-yaml v3 now defaults to 4 spaces, so manually set to 2
yamlEncoder.SetIndent(2)
err := yamlEncoder.Encode(t)
if err != nil {
return fmt.Errorf("error marshaling yaml to %s", path)
}
yamlEncoder.Close()
// Lead with marshaling first so that
// if fails doesn't error with a pre-maturely truncated file
// d, err := yaml.Marshal(t)
// TODO Check if file contents have changed before writing, otherwise return early
// Clear file for writing
f.Truncate(0)
f.Seek(0, 0)
_, err = f.WriteString(yamlDelimLf)
if err != nil {
return fmt.Errorf("error writing to %s: %v", path, err)
}
_, err = f.Write(d.Bytes())
if err != nil {
return fmt.Errorf("error writing to %s: %v", path, err)
}
_, err = f.WriteString(yamlDelimLf)
if err != nil {
return fmt.Errorf("error writing to %s: %v", path, err)
}
// Write markdown content from struct field depending on type CVE or Researcher
switch t := t.(type) {
case CVE:
_, err = f.WriteString(t.Advisory)
if err != nil {
return fmt.Errorf("error writing to %s: %v", path, err)
}
case Researcher:
_, err = f.WriteString(t.Bio)
if err != nil {
return fmt.Errorf("error writing to %s: %v", path, err)
}
default:
return fmt.Errorf("unknown type: %+v", t)
}
return nil
}