...
Source file src/pkg/cmd/go/internal/get/path.go
1
2
3
4
5 package get
6
7 import (
8 "fmt"
9 "strings"
10 "unicode"
11 "unicode/utf8"
12 )
13
14
15
16
17
18
19
20
21
22
23
24 func CheckImportPath(path string) error {
25 if err := checkPath(path, false); err != nil {
26 return fmt.Errorf("malformed import path %q: %v", path, err)
27 }
28 return nil
29 }
30
31
32
33
34
35
36
37 func checkPath(path string, fileName bool) error {
38 if !utf8.ValidString(path) {
39 return fmt.Errorf("invalid UTF-8")
40 }
41 if path == "" {
42 return fmt.Errorf("empty string")
43 }
44 if path[0] == '-' {
45 return fmt.Errorf("leading dash")
46 }
47 if strings.Contains(path, "..") {
48 return fmt.Errorf("double dot")
49 }
50 if strings.Contains(path, "//") {
51 return fmt.Errorf("double slash")
52 }
53 if path[len(path)-1] == '/' {
54 return fmt.Errorf("trailing slash")
55 }
56 elemStart := 0
57 for i, r := range path {
58 if r == '/' {
59 if err := checkElem(path[elemStart:i], fileName); err != nil {
60 return err
61 }
62 elemStart = i + 1
63 }
64 }
65 if err := checkElem(path[elemStart:], fileName); err != nil {
66 return err
67 }
68 return nil
69 }
70
71
72
73 func checkElem(elem string, fileName bool) error {
74 if elem == "" {
75 return fmt.Errorf("empty path element")
76 }
77 if strings.Count(elem, ".") == len(elem) {
78 return fmt.Errorf("invalid path element %q", elem)
79 }
80 if elem[0] == '.' && !fileName {
81 return fmt.Errorf("leading dot in path element")
82 }
83 if elem[len(elem)-1] == '.' {
84 return fmt.Errorf("trailing dot in path element")
85 }
86
87 charOK := pathOK
88 if fileName {
89 charOK = fileNameOK
90 }
91 for _, r := range elem {
92 if !charOK(r) {
93 return fmt.Errorf("invalid char %q", r)
94 }
95 }
96
97
98
99 short := elem
100 if i := strings.Index(short, "."); i >= 0 {
101 short = short[:i]
102 }
103 for _, bad := range badWindowsNames {
104 if strings.EqualFold(bad, short) {
105 return fmt.Errorf("disallowed path element %q", elem)
106 }
107 }
108
109
110
111 if tilde := strings.LastIndexByte(short, '~'); tilde >= 0 && tilde < len(short)-1 {
112 suffix := short[tilde+1:]
113 suffixIsDigits := true
114 for _, r := range suffix {
115 if r < '0' || r > '9' {
116 suffixIsDigits = false
117 break
118 }
119 }
120 if suffixIsDigits {
121 return fmt.Errorf("trailing tilde and digits in path element")
122 }
123 }
124
125 return nil
126 }
127
128
129
130
131 func pathOK(r rune) bool {
132 if r < utf8.RuneSelf {
133 return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
134 '0' <= r && r <= '9' ||
135 'A' <= r && r <= 'Z' ||
136 'a' <= r && r <= 'z'
137 }
138 return unicode.IsLetter(r)
139 }
140
141
142
143
144
145
146 func fileNameOK(r rune) bool {
147 if r < utf8.RuneSelf {
148
149
150
151
152
153
154 const allowed = "!#$%&()+,-.=@[]^_{}~ "
155 if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
156 return true
157 }
158 for i := 0; i < len(allowed); i++ {
159 if rune(allowed[i]) == r {
160 return true
161 }
162 }
163 return false
164 }
165
166
167 return unicode.IsLetter(r)
168 }
169
170
171
172 var badWindowsNames = []string{
173 "CON",
174 "PRN",
175 "AUX",
176 "NUL",
177 "COM1",
178 "COM2",
179 "COM3",
180 "COM4",
181 "COM5",
182 "COM6",
183 "COM7",
184 "COM8",
185 "COM9",
186 "LPT1",
187 "LPT2",
188 "LPT3",
189 "LPT4",
190 "LPT5",
191 "LPT6",
192 "LPT7",
193 "LPT8",
194 "LPT9",
195 }
196
View as plain text