-
Notifications
You must be signed in to change notification settings - Fork 0
/
link.go
124 lines (114 loc) · 2.86 KB
/
link.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
package golem
import (
"net/url"
"strings"
)
type ActionLink struct{}
func (action *ActionLink) Action(ctx *Context, config interface{}) (interface{}, error) {
if linkz, ok := config.([]string); ok {
var links []string
rel, _ := url.Parse(ctx.Link)
for _, l := range linkz {
if link, ok := action.cleanLink(&l, rel, ctx); ok {
links = append(links, link)
}
}
if len(links) > 0 {
SubmitTask(ctx.JobId, &links)
}
} else if link, ok := config.(string); ok {
rel, _ := url.Parse(ctx.Link)
if l, ok := action.cleanLink(&link, rel, ctx); ok {
SubmitTask(ctx.JobId, &[]string{l})
}
}
return nil, nil
}
func (action *ActionLink) cleanLink(link *string, rel *url.URL, ctx *Context) (string, bool) {
if l, err := url.Parse(*link); err == nil {
resolved := ResolveLink(l, rel)
lc := resolved.String()
for _, def := range *ctx.Defs {
if def.MatchPage(&lc) {
return lc, true
}
}
}
return "", false
}
func ResolveLink(link *url.URL, rel *url.URL) url.URL {
if len(link.Host) == 0 {
link.Host = rel.Host
}
if len(link.Scheme) == 0 {
link.Scheme = rel.Scheme
}
if rel.User != nil && link.User == nil {
link.User = rel.User
}
// Resolve relative path
if len(link.Path) > 0 {
path := link.EscapedPath()
relPath := rel.EscapedPath()
if len(path) >= 3 && path[0:3] == "../" { // Down
var counter int
for len(path) >= 3 && path[0:3] == "../" {
counter += 1
path = path[3:]
}
segments := strings.Split(relPath, "/")
var lastSlash bool = false
if len(segments) > 0 && segments[len(segments)-1] == "" {
segments = segments[:len(segments)-2]
lastSlash = true
}
if counter >= len(segments) {
if lastSlash {
path = "/" + path
}
p, _ := url.QueryUnescape(path)
link.Path = p
} else {
if lastSlash {
path = "/" + path
}
pos := len(segments) - counter
segments = segments[:pos]
if len(path) > 0 && path[0] != 47 {
path = "/" + path
}
p, _ := url.QueryUnescape(strings.Join(segments, "/") + path)
link.Path = p
if len(link.Path) > 0 && link.Path[0] != 47 {
link.Path = "/" + link.Path
}
}
} else { // Up and absolute
if path[0] != 47 { // Up
if relPath[len(relPath)-1] != 47 {
path = relPath + "/" + path
} else {
path = relPath + path
}
} // Else absolute
link.Path, _ = url.QueryUnescape(path)
}
}
return *link
}
func (action *ActionLink) ExpandConfig(stages *[]map[string]interface{}, ctx *Context, config interface{}) (interface{}, error) {
conf := config.(map[string]interface{})
template := conf["link"].(string)
return TemplateValue(stages, ctx, &template)
}
func (action *ActionLink) Validate(config interface{}) bool {
if config, ok := config.(map[string]interface{}); ok {
_, ok := config["link"]
return ok
} else {
return false
}
}
func init() {
RegisterAction(new(ActionLink), "link")
}