-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilter.go
More file actions
104 lines (96 loc) · 2.81 KB
/
Copy pathfilter.go
File metadata and controls
104 lines (96 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package thuder
import (
"fmt"
"regexp"
"time"
)
//Filter blocks or allows a file copy
type Filter struct {
Allow bool //allow or block if filter is matched
Direction string `json:",omitempty"` //(pull/push/"")
FolderOnly bool `json:",omitempty"` //matches only folders
FileOnly bool `json:",omitempty"` //matches only files
PathRx string `json:",omitempty"` //regexp that matches the folder path
pathRx *regexp.Regexp
NameRx string `json:",omitempty"` //regexp that matches the filename
nameRx *regexp.Regexp
LastModifiedDays float32 `json:",omitempty"` //only matches within these days, 0 is unlimited
SubFilters []Filter `json:",omitempty"` //on match, use subfilters
}
//Prepare prepares a Filter for usage, and return any errors in filter definition
func (f *Filter) Prepare() error {
if len(f.Direction) > 0 && f.Direction != "pull" && f.Direction != "push" {
return fmt.Errorf("unknown Direction %v should be (pull/push/\"\")", f.Direction)
}
if f.FolderOnly && f.FileOnly {
return fmt.Errorf("both FolderOnly and FileOnly")
}
var err error
f.pathRx, err = regexp.Compile(f.PathRx)
if err != nil {
return fmt.Errorf("PathRx %v", err)
}
f.nameRx, err = regexp.Compile(f.NameRx)
if err != nil {
return fmt.Errorf("NameRx %v", err)
}
if f.LastModifiedDays < 0 {
return fmt.Errorf("LastModifiedDays (%v) should be positive", f.LastModifiedDays)
}
return PrepareFilters(f.SubFilters)
}
//PrepareFilters runs perpare on a slice of filters
func PrepareFilters(fs []Filter) error {
for i := 0; i < len(fs); i++ {
err := fs[i].Prepare()
if err != nil {
return fmt.Errorf("sub(%v) %v", i, err)
}
}
return nil
}
//Match tests if Node matches filter, and if matched, is it allowed or blocked
func (f *Filter) Match(n *Node, push bool, now time.Time) (match bool, allow bool) {
if len(f.Direction) > 1 {
if push && f.Direction != "push" {
return false, false
}
if !push && f.Direction != "pull" {
return false, false
}
}
if n.IsDir() {
if f.FileOnly {
return false, false
}
} else if f.FolderOnly {
return false, false
}
if f.pathRx != nil && !f.pathRx.MatchString(n.fc.from) {
return false, false
}
if f.nameRx != nil && !f.nameRx.MatchString(n.info.Name()) {
return false, false
}
if f.LastModifiedDays != 0 {
duration := time.Duration(f.LastModifiedDays * float32(time.Hour*24))
if n.ModTime().Add(duration).Before(now) {
return false, false
}
}
m, a := MatchFilters(f.SubFilters, n, push, now)
if m {
return m, a
}
return true, f.Allow
}
//MatchFilters tests a node against filters
func MatchFilters(fs []Filter, n *Node, push bool, now time.Time) (match bool, allow bool) {
for _, sub := range fs {
m, a := sub.Match(n, push, now)
if m {
return m, a
}
}
return false, false
}