forked from manno/xsltd-web
-
Notifications
You must be signed in to change notification settings - Fork 1
/
web_repo.go
109 lines (92 loc) · 2.28 KB
/
web_repo.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
package main
import (
"errors"
"net/url"
"os"
"path"
"strings"
)
type WebRepo struct {
WebRoot string
}
type XMLFile struct {
URLPath string
FilesystemPath string
}
func (x *XMLFile) IsXML() bool {
return hasExtension(x.FilesystemPath, "xml")
}
func (x *XMLFile) Exists() bool {
return fileExists(x.FilesystemPath)
}
func NewWebRepo(webRoot string) *WebRepo {
return &WebRepo{WebRoot: webRoot}
}
func (w *WebRepo) FindXML(requestPath string) (*XMLFile, error) {
xmlFile, err := w.cleanPath(requestPath)
if err != nil {
return nil, err
}
if xmlFile.URLPath == "" || xmlFile.URLPath == "/" {
xmlFile.URLPath = "index.xml"
xmlFile.FilesystemPath = path.Join(w.WebRoot, "index.xml")
return xmlFile, nil
}
if hasExtension(xmlFile.FilesystemPath, "xml") && fileExists(xmlFile.FilesystemPath) {
return xmlFile, nil
}
if hasExtension(xmlFile.FilesystemPath, "html") {
x := pathWithoutExt(xmlFile.FilesystemPath) + ".xml"
if fileExists(x) {
xmlFile.URLPath = pathWithoutExt(xmlFile.URLPath) + ".xml"
xmlFile.FilesystemPath = x
}
return xmlFile, nil
}
if fileExists(xmlFile.FilesystemPath + ".xml") {
return &XMLFile{
URLPath: xmlFile.URLPath + ".xml",
FilesystemPath: xmlFile.FilesystemPath + ".xml",
}, nil
}
return xmlFile, nil
}
func (w *WebRepo) cleanPath(urlPath string) (*XMLFile, error) {
urlPath, err := url.PathUnescape(urlPath)
if err != nil {
return nil, err
}
p := path.Clean(urlPath)
f, err := prefixWebRoot(w.WebRoot, p)
if err != nil {
return nil, err
}
return &XMLFile{URLPath: p, FilesystemPath: f}, nil
}
func prefixWebRoot(webRoot string, relative string) (string, error) {
abs := path.Join(webRoot, relative)
if strings.Index(abs, webRoot) != 0 {
return "", errors.New("requested path is not inside webroot")
}
return abs, nil
}
func pathWithoutExt(absPath string) string {
ext := path.Ext(absPath)
return absPath[0 : len(absPath)-len(ext)]
}
func hasExtension(requestPath, extension string) bool {
pos := strings.LastIndex(requestPath, extension)
if pos > -1 && pos == len(requestPath)-len(extension) {
if requestPath[pos-1] == '.' || requestPath[pos-1] == '?' {
return true
}
}
return false
}
func fileExists(path string) bool {
_, err := os.Stat(path)
if err != nil {
return false
}
return true
}