-
Notifications
You must be signed in to change notification settings - Fork 19
/
mixpayloads.go
149 lines (132 loc) · 3.15 KB
/
mixpayloads.go
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Package mix used to mix payload with different rules and scopes
package mix
import (
"net/url"
"path"
"strings"
"github.com/gokitx/pkgs/urlx"
)
func Payloads(u url.URL, payloads []string, rules []Rule, scopes []Scope) []url.URL {
var urls []url.URL
for _, scope := range scopes {
switch scope {
case ScopeQuery:
urls = append(urls, mixQuery(u, payloads, rules)...)
case ScopePath:
urls = append(urls, mixPath(u, payloads, rules)...)
case ScopeFragment:
urls = append(urls, mixFragment(u, payloads, rules)...)
}
}
return urls
}
func mixQuery(u url.URL, payloads []string, rules []Rule) []url.URL {
if len(u.Query()) == 0 {
return nil
}
baseQuery := u.Query()
urls := make([]url.URL, len(payloads)*len(rules)*len(baseQuery))
var index int
for _, payload := range payloads {
for key := range baseQuery {
for _, rule := range rules {
u.RawQuery = generateQueryWithRule(
urlx.CloneUrlValues(baseQuery),
key, payload, rule,
).Encode()
urls[index] = u
index++
}
}
}
return urls
}
func generateQueryWithRule(query url.Values, key, payload string, rule Rule) url.Values {
switch rule {
case RuleAppendPrefix:
query.Set(key, payload+query.Get(key))
return query
case RuleAppendSuffix:
query.Set(key, query.Get(key)+payload)
return query
case RuleReplace:
query.Set(key, payload)
return query
}
return query
}
func mixPath(u url.URL, payloads []string, rules []Rule) []url.URL {
var urls []url.URL
paths := strings.Split(u.Path, "/")
if len(paths) <= 1 {
return nil
}
for _, payload := range payloads {
for index := range paths {
for _, rule := range rules {
if paths[index] == "" {
continue
}
brefore := paths[index]
paths[index] = generateStrWithRule(brefore, payload, rule)
u.Path = path.Join(paths...)
paths[index] = brefore
urls = append(urls, u)
}
}
}
return urls
}
func generateStrWithRule(old, payload string, rule Rule) string {
switch rule {
case RuleAppendPrefix:
return payload + old
case RuleAppendSuffix:
return old + payload
case RuleReplace:
return payload
}
return old
}
func mixFragment(u url.URL, payloads []string, rules []Rule) []url.URL {
var urls []url.URL
if u.Fragment == "" {
return nil
}
fragment := u.Fragment
for _, payload := range payloads {
for _, rule := range rules {
u.Fragment = generateStrWithRule(fragment, payload, rule)
urls = append(urls, u)
}
}
return urls
}
// mixFilter decides whether a payload or url is allowed to be mixed or not.
// TODO: filter numeric or string types
type mixFilter int
const (
FilterNumeric mixFilter = iota + 1
FilterString
FilterIP
FilterDomain
FilterURI
FilterEmail
)
type Rule int
const (
// RuleAppendPrefix appends the payload to the beginning of the string
RuleAppendPrefix Rule = iota + 1
// RuleAppendSuffix appends the payload to the end of the string
RuleAppendSuffix
// RuleReplace replaces the string with the payload
RuleReplace
)
var DefaultMixRules = []Rule{RuleAppendPrefix, RuleAppendSuffix, RuleReplace}
type Scope int
const (
ScopeQuery Scope = iota + 1
ScopePath
ScopeFragment
)
var DefaultScopes = []Scope{ScopeQuery, ScopeFragment}