From ae2c7d00a95d67f21c72eac9c915701313b3646b Mon Sep 17 00:00:00 2001
From: Simon Zolin <s.zolin@adguard.com>
Date: Mon, 18 Mar 2019 14:12:04 +0300
Subject: [PATCH] * control: enable/disable filter: move code to a separate
 function

* don't start updating all filters after 1 filter has been enabled
* unload filter data on disable
---
 control.go | 26 ++------------------------
 filter.go  | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/control.go b/control.go
index 0dbd9c42..d1d459f5 100644
--- a/control.go
+++ b/control.go
@@ -688,24 +688,12 @@ func handleFilteringEnableURL(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	found := false
-	config.Lock()
-	for i := range config.Filters {
-		filter := &config.Filters[i] // otherwise we will be operating on a copy
-		if filter.URL == url {
-			filter.Enabled = true
-			found = true
-		}
-	}
-	config.Unlock()
-
+	found := filterEnable(url, true)
 	if !found {
 		http.Error(w, "URL parameter was not previously added", http.StatusBadRequest)
 		return
 	}
 
-	// kick off refresh of rules from new URLs
-	refreshFiltersIfNecessary(false)
 	httpUpdateConfigReloadDNSReturnOK(w, r)
 }
 
@@ -728,17 +716,7 @@ func handleFilteringDisableURL(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	found := false
-	config.Lock()
-	for i := range config.Filters {
-		filter := &config.Filters[i] // otherwise we will be operating on a copy
-		if filter.URL == url {
-			filter.Enabled = false
-			found = true
-		}
-	}
-	config.Unlock()
-
+	found := filterEnable(url, false)
 	if !found {
 		http.Error(w, "URL parameter was not previously added", http.StatusBadRequest)
 		return
diff --git a/filter.go b/filter.go
index 6540e384..400073da 100644
--- a/filter.go
+++ b/filter.go
@@ -44,6 +44,34 @@ func userFilter() filter {
 	}
 }
 
+// Enable or disable a filter
+func filterEnable(url string, enable bool) bool {
+	r := false
+	config.Lock()
+	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)
+				}
+			} else {
+				filter.unload()
+			}
+			r = true
+			break
+		}
+	}
+	config.Unlock()
+	return r
+}
+
 // Load filters from the disk
 // And if any filter has zero ID, assign a new one
 func loadFilters() {
@@ -284,6 +312,12 @@ func (filter *filter) load() error {
 	return nil
 }
 
+// Clear filter rules
+func (filter *filter) unload() {
+	filter.Rules = []string{}
+	filter.RulesCount = 0
+}
+
 // Path to the filter contents
 func (filter *filter) Path() string {
 	return filepath.Join(config.ourWorkingDir, dataDir, filterDir, strconv.FormatInt(filter.ID, 10)+".txt")