From b3dc36421f133ea6983574891720e974cf7974dd Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Mon, 31 Jan 2022 11:09:58 -0500 Subject: initial commit --- internal/feed/meta.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 internal/feed/meta.go (limited to 'internal/feed/meta.go') diff --git a/internal/feed/meta.go b/internal/feed/meta.go new file mode 100644 index 0000000..da2849d --- /dev/null +++ b/internal/feed/meta.go @@ -0,0 +1,104 @@ +package feed + +import ( + "bufio" + "encoding/hex" + "fmt" + "io" + "strconv" + "strings" + "time" +) + +// NVD metadata. +type Meta struct { + LastModifiedDate time.Time // last modified time + Size uint64 // uncompressed size, in bytes + ZipSize uint64 // zip file size, in bytes + GzSize uint64 // gz file size, in bytes + Sha256 [32]byte // sha256 hash of uncompressed data +} + +func parseMetaSize(name, val string) (uint64, error) { + // parse value, check for error + v, err := strconv.ParseUint(val, 10, 64) + if err == nil { + // return size + return v, nil + } else { + // return error + return 0, fmt.Errorf("invalid %s: \"%s\"", name, val) + } +} + +// Unmarshal new Metadata from reader. +func NewMeta(r io.Reader) (*Meta, error) { + // declare result + var m Meta + + // create scanner + scanner := bufio.NewScanner(r) + + // read lines + for scanner.Scan() { + // split into key/value pair, check for error + pair := strings.SplitN(scanner.Text(), ":", 2) + if len(pair) != 2 { + return nil, fmt.Errorf("bad meta line: \"%s\"", scanner.Text()) + } + + switch pair[0] { + case "lastModifiedDate": + // parse time, check for error + if err := m.LastModifiedDate.UnmarshalText([]byte(pair[1])); err != nil { + return nil, err + } + case "size": + if v, err := parseMetaSize("size", pair[1]); err == nil { + m.Size = v + } else { + return nil, err + } + case "zipSize": + if v, err := parseMetaSize("zipSize", pair[1]); err == nil { + m.ZipSize = v + } else { + return nil, err + } + case "gzSize": + if v, err := parseMetaSize("gzSize", pair[1]); err == nil { + m.GzSize = v + } else { + return nil, err + } + case "sha256": + // check hash length + if len(pair[1]) != 64 { + return nil, fmt.Errorf("invalid sha256 hash length: \"%d\"", len(pair[1])) + } + + // decode hex, check for error + buf, err := hex.DecodeString(pair[1]) + if err != nil { + return nil, fmt.Errorf("invalid sha256 hash: %v", err) + } + + // save to buffer, check for error + len := copy(m.Sha256[:], buf[0:32]) + if len != 32 { + return nil, fmt.Errorf("invalid sha256 hash length: %d", len) + } + default: + // return error + return nil, fmt.Errorf("unknown key: \"%s\"", pair[0]) + } + } + + // check for scanner error + if err := scanner.Err(); err != nil { + return nil, err + } + + // return success + return &m, nil +} -- cgit v1.2.3