diff options
Diffstat (limited to 'internal/blocklist')
| -rw-r--r-- | internal/blocklist/blocklist.go | 52 | ||||
| -rw-r--r-- | internal/blocklist/blocklist_test.go | 59 |
2 files changed, 95 insertions, 16 deletions
diff --git a/internal/blocklist/blocklist.go b/internal/blocklist/blocklist.go index 34a456d..84d758c 100644 --- a/internal/blocklist/blocklist.go +++ b/internal/blocklist/blocklist.go @@ -24,30 +24,50 @@ func Load(path string) (*Blocklist, error) { sc := bufio.NewScanner(f) for sc.Scan() { line := strings.TrimSpace(sc.Text()) - if line == "" || line[0] == '#' { + if line == "" || line[0] == '#' || line[0] == '!' { continue } - line = strings.ToLower(line) - line = strings.TrimSuffix(line, ".") - bl.domains[line] = struct{}{} + domain := parseLine(line) + if domain != "" && !strings.HasPrefix(domain, "*.") { + bl.domains[strings.ToLower(domain)] = struct {}{} + } } return bl, sc.Err() } -func (bl *Blocklist) Blocked(qname string) bool { - qname = strings.ToLower(qname) - qname = strings.TrimSuffix(qname, ".") +func parseLine(line string) string { + line = strings.TrimSpace(line) - if _, ok := bl.domains[qname]; ok { - return true + // 1. Hosts: "0.0.0.0 domain" "127.0.0.1 domain # comment" + if strings.HasPrefix(line, "0.0.0.0 ") { + line = line[8:] + } else if strings.HasPrefix(line, "127.0.0.1 ") { + line = line[10:] + } else if strings.HasPrefix(line, "||") { + // 2. AdGuard / uBlock: "||domain^$attr" + line = line[2:] + // Cut at ^ or $ + if idx := strings.IndexAny(line, "^$"); idx >= 0 { + line = line[:idx] + } } - for i := 0; i < len(qname); i++ { - if qname[i] == '.' { - if _, ok := bl.domains[qname[i+1:]]; ok { - return true - } - } + if idx := strings.IndexAny(line, " \t#"); idx >= 0 { + line = line[:idx] + } + + line = strings.TrimSpace(line) + line = strings.TrimSuffix(line, ".") + + if strings.ContainsAny(line, "/:\\?") { + return "" } - return false + return line +} + +func (bl *Blocklist) Blocked(qname string) bool { + qname = strings.ToLower(qname) + qname = strings.TrimSuffix(qname, ".") + _, ok := bl.domains[qname] + return ok } diff --git a/internal/blocklist/blocklist_test.go b/internal/blocklist/blocklist_test.go new file mode 100644 index 0000000..0104bc9 --- /dev/null +++ b/internal/blocklist/blocklist_test.go @@ -0,0 +1,59 @@ +package blocklist + +import ( + "os" + "testing" +) + +func TestParseLine(t *testing.T) { + tests := []struct{in,out string}{ + {"0.0.0.0 domain.com", "domain.com"}, + {"0.0.0.0 domain.com # foo", "domain.com"}, + {"0.0.0.0 *.domain.com", "*.domain.com"}, + {"||domain.com^", "domain.com"}, + {"||domain.com^$script", "domain.com"}, + {"",""}, + {"# comment", ""}, + {"||*.domain.com^", "*.domain.com"}, + } + for _, tt := range tests { + if got := parseLine(tt.in); got != tt.out { + t.Errorf("parseLine(%q) = %q, want %q", tt.in, got, tt.out) + } + } +} + +func TestBlocked(t *testing.T) { + tmp, _ := os.CreateTemp("", "blocklist-*.txt") + tmp.WriteString("radhitya.org\n") + tmp.WriteString("0.0.0.0 ads.test.com\n") + tmp.WriteString("||example.net^\n") + tmp.WriteString("||*.domain.com^\n") + tmp.Close() + defer os.Remove(tmp.Name()) + + bl, err := Load(tmp.Name()) + if err != nil { + t.Fatal(err) + } + + if !bl.Blocked("radhitya.org") { + t.Error("radhitya.org shall be blocked") + } + if bl.Blocked("alif.radhitya.org") { + t.Error("alif.radhitya.org shall NOT be blocked") + } + if !bl.Blocked("ads.test.com") { + t.Error("ads.test.com shall be blocked (hosts format)") + } + if !bl.Blocked("example.net") { + t.Error("example.net shall be blocked (adguard format)") + } + + if bl.Blocked("domain.com") { + t.Error("domain.com shall NOT be blocked (wildcard skipped)") + } + if bl.Blocked("sub.domain.com") { + t.Error("sub.domain.com shall NOT be blocked (wildcard skipped)") + } +} |
