Merge: + filters: support filters from local disk

Close #817

* commit '81309c707a70ff15a7075fb5906962764b470ca7':
  + filters: support filters from local disk
This commit is contained in:
Simon Zolin 2020-04-09 13:51:28 +03:00
commit 1739d7975f
4 changed files with 38 additions and 24 deletions

View File

@ -1439,7 +1439,7 @@ Request:
{ {
"name": "..." "name": "..."
"url": "..." "url": "..." // URL or an absolute file path
"whitelist": true "whitelist": true
} }

View File

@ -8,15 +8,22 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath"
"strings" "strings"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/util"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
// IsValidURL - return TRUE if URL is valid // IsValidURL - return TRUE if URL or file path is valid
func IsValidURL(rawurl string) bool { func IsValidURL(rawurl string) bool {
if filepath.IsAbs(rawurl) {
// this is a file path
return util.FileExists(rawurl)
}
url, err := url.ParseRequestURI(rawurl) url, err := url.ParseRequestURI(rawurl)
if err != nil { if err != nil {
return false //Couldn't even parse the rawurl return false //Couldn't even parse the rawurl
@ -42,7 +49,7 @@ func (f *Filtering) handleFilteringAddURL(w http.ResponseWriter, r *http.Request
} }
if !IsValidURL(fj.URL) { if !IsValidURL(fj.URL) {
http.Error(w, "Invalid URL", http.StatusBadRequest) http.Error(w, "Invalid URL or file path", http.StatusBadRequest)
return return
} }
@ -100,11 +107,6 @@ func (f *Filtering) handleFilteringRemoveURL(w http.ResponseWriter, r *http.Requ
return return
} }
if !IsValidURL(req.URL) {
http.Error(w, "URL parameter is not valid request URL", http.StatusBadRequest)
return
}
// go through each element and delete if url matches // go through each element and delete if url matches
config.Lock() config.Lock()
newFilters := []filter{} newFilters := []filter{}
@ -154,7 +156,7 @@ func (f *Filtering) handleFilteringSetURL(w http.ResponseWriter, r *http.Request
} }
if !IsValidURL(fj.URL) { if !IsValidURL(fj.URL) {
http.Error(w, "invalid URL", http.StatusBadRequest) http.Error(w, "invalid URL or file path", http.StatusBadRequest)
return return
} }

View File

@ -69,7 +69,7 @@ func defaultFilters() []filter {
// field ordering is important -- yaml fields will mirror ordering from here // field ordering is important -- yaml fields will mirror ordering from here
type filter struct { type filter struct {
Enabled bool Enabled bool
URL string URL string // URL or a file path
Name string `yaml:"name"` Name string `yaml:"name"`
RulesCount int `yaml:"-"` RulesCount int `yaml:"-"`
LastUpdated time.Time `yaml:"-"` LastUpdated time.Time `yaml:"-"`
@ -500,6 +500,7 @@ func (f *Filtering) update(filter *filter) (bool, error) {
return b, err return b, err
} }
// nolint(gocyclo)
func (f *Filtering) updateIntl(filter *filter) (bool, error) { func (f *Filtering) updateIntl(filter *filter) (bool, error) {
log.Tracef("Downloading update for filter %d from %s", filter.ID, filter.URL) log.Tracef("Downloading update for filter %d from %s", filter.ID, filter.URL)
@ -514,18 +515,29 @@ func (f *Filtering) updateIntl(filter *filter) (bool, error) {
} }
}() }()
resp, err := Context.client.Get(filter.URL) var reader io.Reader
if resp != nil && resp.Body != nil { if filepath.IsAbs(filter.URL) {
defer resp.Body.Close() f, err := os.Open(filter.URL)
} if err != nil {
if err != nil { return false, fmt.Errorf("open file: %s", err)
log.Printf("Couldn't request filter from URL %s, skipping: %s", filter.URL, err) }
return false, err defer f.Close()
} reader = f
} else {
resp, err := Context.client.Get(filter.URL)
if resp != nil && resp.Body != nil {
defer resp.Body.Close()
}
if err != nil {
log.Printf("Couldn't request filter from URL %s, skipping: %s", filter.URL, err)
return false, err
}
if resp.StatusCode != 200 { if resp.StatusCode != 200 {
log.Printf("Got status code %d from URL %s, skipping", resp.StatusCode, filter.URL) log.Printf("Got status code %d from URL %s, skipping", resp.StatusCode, filter.URL)
return false, fmt.Errorf("got status code != 200: %d", resp.StatusCode) return false, fmt.Errorf("got status code != 200: %d", resp.StatusCode)
}
reader = resp.Body
} }
htmlTest := true htmlTest := true
@ -534,7 +546,7 @@ func (f *Filtering) updateIntl(filter *filter) (bool, error) {
buf := make([]byte, 64*1024) buf := make([]byte, 64*1024)
total := 0 total := 0
for { for {
n, err := resp.Body.Read(buf) n, err := reader.Read(buf)
total += n total += n
if htmlTest { if htmlTest {

View File

@ -507,7 +507,7 @@ paths:
tags: tags:
- filtering - filtering
operationId: filteringAddURL operationId: filteringAddURL
summary: 'Add filter URL' summary: 'Add filter URL or an absolute file path'
consumes: consumes:
- application/json - application/json
parameters: parameters:
@ -1495,7 +1495,7 @@ definitions:
name: name:
type: "string" type: "string"
url: url:
description: "URL containing filtering rules" description: "URL or an absolute path to the file containing filtering rules"
type: "string" type: "string"
example: "https://filters.adtidy.org/windows/filters/15.txt" example: "https://filters.adtidy.org/windows/filters/15.txt"
RemoveUrlRequest: RemoveUrlRequest: