aboutsummaryrefslogtreecommitdiff
path: root/blockd.go
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2022-05-22 21:29:35 +0700
committerShulhan <ms@kilabit.info>2022-05-22 21:51:47 +0700
commit0b92dbb8463dee31c005c59f67c2bf754a9eae12 (patch)
treea95162fc3aaa88ce772f9b7c8b79747c225a0ba8 /blockd.go
parent89494ecacdd03426da17def52e35a1a66c9630eb (diff)
downloadrescached-0b92dbb8463dee31c005c59f67c2bf754a9eae12.tar.xz
all: export and rename the hostsBlock type to Blockd
In the Environment, we have a field HostsBlocks that reference an unexported type hostsFile. In order for any package to be able to use this field, we need to export this type. While at it, we rename the type from hostsBlock to Blockd to make it simple and consistent with name.
Diffstat (limited to 'blockd.go')
-rw-r--r--blockd.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/blockd.go b/blockd.go
new file mode 100644
index 0000000..398bb96
--- /dev/null
+++ b/blockd.go
@@ -0,0 +1,148 @@
+// SPDX-FileCopyrightText: 2020 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package rescached
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+ "time"
+)
+
+const (
+ lastUpdatedFormat = "2006-01-02 15:04:05 MST"
+)
+
+type Blockd struct {
+ lastUpdated time.Time
+
+ Name string `ini:"::name"` // Derived from hostname in URL.
+ URL string `ini:"::url"`
+
+ file string
+ fileDisabled string
+ LastUpdated string
+
+ IsEnabled bool // True if the hosts file un-hidden in block.d directory.
+ isFileExist bool // True if the file exist and enabled or disabled.
+}
+
+// disable the hosts block by prefixing the file name with single dot.
+func (hb *Blockd) disable() (err error) {
+ err = os.Rename(hb.file, hb.fileDisabled)
+ if err != nil {
+ return fmt.Errorf("disable: %w", err)
+ }
+ hb.IsEnabled = false
+ return nil
+}
+
+// enable the hosts block file by removing the dot prefix from file name.
+func (hb *Blockd) enable() (err error) {
+ if hb.isFileExist {
+ err = os.Rename(hb.fileDisabled, hb.file)
+ } else {
+ err = os.WriteFile(hb.file, []byte(""), 0600)
+ }
+ if err != nil {
+ return fmt.Errorf("enable: %w", err)
+ }
+ hb.IsEnabled = true
+ hb.isFileExist = true
+ return nil
+}
+
+func (hb *Blockd) init(pathDirBlock string) {
+ var (
+ fi os.FileInfo
+ err error
+ )
+
+ hb.file = filepath.Join(pathDirBlock, hb.Name)
+ hb.fileDisabled = filepath.Join(pathDirBlock, "."+hb.Name)
+
+ fi, err = os.Stat(hb.file)
+ if err != nil {
+ hb.IsEnabled = false
+
+ fi, err = os.Stat(hb.fileDisabled)
+ if err != nil {
+ return
+ }
+
+ hb.isFileExist = true
+ } else {
+ hb.IsEnabled = true
+ hb.isFileExist = true
+ }
+
+ hb.lastUpdated = fi.ModTime()
+ hb.LastUpdated = hb.lastUpdated.Format(lastUpdatedFormat)
+}
+
+// isOld will return true if the host file has not been updated since seven
+// days.
+func (hb *Blockd) isOld() bool {
+ oneWeek := 7 * 24 * time.Hour
+ lastWeek := time.Now().Add(-1 * oneWeek)
+
+ return hb.lastUpdated.Before(lastWeek)
+}
+
+func (hb *Blockd) update() (err error) {
+ if !hb.isOld() {
+ return nil
+ }
+
+ var (
+ logp = "Blockd.update"
+
+ res *http.Response
+ body []byte
+ errClose error
+ )
+
+ fmt.Printf("%s %s: updating ...\n", logp, hb.Name)
+
+ err = os.MkdirAll(filepath.Dir(hb.file), 0700)
+ if err != nil {
+ return fmt.Errorf("%s %s: %w", logp, hb.Name, err)
+ }
+
+ res, err = http.Get(hb.URL)
+ if err != nil {
+ return fmt.Errorf("%s %s: %w", logp, hb.Name, err)
+ }
+ defer func() {
+ errClose = res.Body.Close()
+ if errClose != nil {
+ log.Printf("%s %q: %s", logp, hb.Name, err)
+ }
+ }()
+
+ body, err = io.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("%s %q: %w", logp, hb.Name, err)
+ }
+
+ body = bytes.ReplaceAll(body, []byte("\r\n"), []byte("\n"))
+
+ if hb.IsEnabled {
+ err = os.WriteFile(hb.file, body, 0644)
+ } else {
+ err = os.WriteFile(hb.fileDisabled, body, 0644)
+ }
+ if err != nil {
+ return fmt.Errorf("%s %q: %w", logp, hb.Name, err)
+ }
+
+ hb.lastUpdated = time.Now()
+ hb.LastUpdated = hb.lastUpdated.Format(lastUpdatedFormat)
+
+ return nil
+}