diff --git a/AGHTechDoc.md b/AGHTechDoc.md index e8f98db4..6e99cbaa 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1338,9 +1338,13 @@ Request: POST /control/filtering/set_url { + "url": "..." + "data": { + "name": "..." "url": "..." "enabled": true | false } + } Response: diff --git a/home/control_filtering.go b/home/control_filtering.go index 5b4b963e..6188c875 100644 --- a/home/control_filtering.go +++ b/home/control_filtering.go @@ -137,12 +137,18 @@ func handleFilteringRemoveURL(w http.ResponseWriter, r *http.Request) { } type filterURLJSON struct { + Name string `json:"name"` URL string `json:"url"` Enabled bool `json:"enabled"` } +type filterURLReq struct { + URL string `json:"url"` + Data filterURLJSON `json:"data"` +} + func handleFilteringSetURL(w http.ResponseWriter, r *http.Request) { - fj := filterURLJSON{} + fj := filterURLReq{} err := json.NewDecoder(r.Body).Decode(&fj) if err != nil { httpError(w, http.StatusBadRequest, "json decode: %s", err) @@ -154,14 +160,34 @@ func handleFilteringSetURL(w http.ResponseWriter, r *http.Request) { return } - found := filterEnable(fj.URL, fj.Enabled) - if !found { + f := filter{ + Enabled: fj.Data.Enabled, + Name: fj.Data.Name, + URL: fj.Data.URL, + } + status := filterSetProperties(fj.URL, f) + if (status & statusFound) == 0 { http.Error(w, "URL doesn't exist", http.StatusBadRequest) return } + if (status & statusURLExists) != 0 { + http.Error(w, "URL already exists", http.StatusBadRequest) + return + } onConfigModified() - enableFilters(true) + if (status & statusURLChanged) != 0 { + if fj.Data.Enabled { + // download new filter and apply its rules + refreshStatus = 1 + refreshLock.Lock() + _, _ = refreshFiltersIfNecessary(true) + refreshLock.Unlock() + } + + } else if (status & statusEnabledChanged) != 0 { + enableFilters(true) + } } func handleFilteringSetRules(w http.ResponseWriter, r *http.Request) { diff --git a/home/filter.go b/home/filter.go index 9fe2a750..5a810c7e 100644 --- a/home/filter.go +++ b/home/filter.go @@ -68,45 +68,80 @@ func userFilter() filter { return f } -// Enable or disable a filter -func filterEnable(url string, enable bool) bool { - r := false +const ( + statusFound = 1 + statusEnabledChanged = 2 + statusURLChanged = 4 + statusURLExists = 8 +) + +// Update properties for a filter specified by its URL +// Return status* flags. +func filterSetProperties(url string, newf filter) int { + r := 0 config.Lock() + defer config.Unlock() + for i := range config.Filters { - filter := &config.Filters[i] // otherwise we will be operating on a copy - if filter.URL == url { - filter.Enabled = enable - if enable { - e := filter.load() - if e != nil { - // This isn't a fatal error, - // because it may occur when someone removes the file from disk. - // In this case the periodic update task will try to download the file. - filter.LastUpdated = time.Time{} - log.Tracef("%s filter load: %v", url, e) + f := &config.Filters[i] + if f.URL != url { + continue + } + + log.Debug("filter: set properties: %s: {%s %s %v}", + f.URL, newf.Name, newf.URL, newf.Enabled) + f.Name = newf.Name + + if f.URL != newf.URL { + r |= statusURLChanged + if filterExistsNoLock(newf.URL) { + return statusURLExists + } + f.URL = newf.URL + f.unload() + f.LastUpdated = time.Time{} + } + + if f.Enabled != newf.Enabled { + r |= statusEnabledChanged + f.Enabled = newf.Enabled + if f.Enabled { + if (r & statusURLChanged) == 0 { + e := f.load() + if e != nil { + // This isn't a fatal error, + // because it may occur when someone removes the file from disk. + // In this case the periodic update task will try to download the file. + f.LastUpdated = time.Time{} + } } } else { - filter.unload() + f.unload() } - r = true - break } + + return r | statusFound } - config.Unlock() - return r + return 0 } // Return TRUE if a filter with this URL exists func filterExists(url string) bool { - r := false config.RLock() + r := filterExistsNoLock(url) + config.RUnlock() + return r +} + +// Return TRUE if a filter with this URL exists +func filterExistsNoLock(url string) bool { + r := false for i := range config.Filters { if config.Filters[i].URL == url { r = true break } } - config.RUnlock() return r }