aboutsummaryrefslogtreecommitdiff
path: root/nvdmirror/jsoncache.go
diff options
context:
space:
mode:
Diffstat (limited to 'nvdmirror/jsoncache.go')
-rw-r--r--nvdmirror/jsoncache.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/nvdmirror/jsoncache.go b/nvdmirror/jsoncache.go
new file mode 100644
index 0000000..7e84a94
--- /dev/null
+++ b/nvdmirror/jsoncache.go
@@ -0,0 +1,131 @@
+package nvdmirror
+
+import (
+ "compress/gzip"
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "time"
+)
+
+// JSON file backed URL cache.
+type JsonCache struct {
+ dirty bool // has the cache been modified?
+ path string // backing JSON file
+ vals map[string]Entry // entries
+}
+
+// Create new JSON cache.
+func NewJsonCache(path string) (JsonCache, error) {
+ r := JsonCache {
+ path: path,
+ }
+
+ // open path
+ f, err := os.OpenFile(path, os.O_CREATE, 0640)
+ if err != nil {
+ return r, err
+ }
+ defer f.Close()
+
+ // stat file
+ st, err := f.Stat()
+ if err != nil {
+ return r, err
+ }
+
+ vals := make(map[string]Entry)
+ if st.Size() > 0 {
+ // create gzip reader
+ zr, err := gzip.NewReader(f)
+ if err != nil {
+ return r, err
+ }
+
+ // read/decode json
+ d := json.NewDecoder(zr)
+ if err := d.Decode(&vals); err != nil {
+ return r, err
+ }
+ }
+
+ // save path and values
+ r.path = path
+ r.vals = vals
+
+ // return success
+ return r, nil
+}
+
+// Get cache entry
+func (me JsonCache) Get(s string) (map[string]string, bool) {
+ if e, ok := me.vals[s]; ok {
+ return e.Headers, ok
+ } else {
+ return nil, false
+ }
+}
+
+// Set cache entry.
+func (me *JsonCache) Set(s string, headers map[string]string) error {
+ // mark cache as dirty
+ me.dirty = true
+
+ // copy map to internal storage
+ newHeaders := make(map[string]string)
+ for k, v := range(headers) {
+ newHeaders[k] = v
+ }
+
+ // update entry
+ me.vals[s] = Entry {
+ Time: time.Now(),
+ Headers: newHeaders,
+ }
+
+ // return success
+ return nil
+}
+
+// Remove cache entry, if it exists.
+func (me *JsonCache) Delete(s string) error {
+ me.dirty = true
+ delete(me.vals, s)
+ return nil
+}
+
+// Save and close cache.
+func (me *JsonCache) Close() error {
+ if !me.dirty {
+ // return success
+ return nil
+ }
+
+ // open temp output file
+ t, err := os.CreateTemp(filepath.Dir(me.path), "")
+ if err != nil {
+ return err
+ }
+ defer os.Remove(t.Name())
+
+ // encode/compress JSON
+ zw := gzip.NewWriter(t)
+ e := json.NewEncoder(zw)
+ if err = e.Encode(me.vals); err != nil {
+ return err
+ }
+
+ // flush changes
+ if err = zw.Flush(); err != nil {
+ return err
+ }
+
+ // rename to destination file
+ if err = os.Rename(t.Name(), me.path); err != nil {
+ return err
+ }
+
+ // Mark cache as clean, return success.
+ me.dirty = false
+ return nil
+}