validate.gno
2.17 Kb · 81 lines
1package skins
2
3// The string rules below are what makes the hand-built JSON and the markdown
4// of this realm safe: every string that is stored and later printed went
5// through one of them, and none of them lets a quote, a backslash, a pipe, a
6// bracket or a control character in.
7
8const (
9 maxIDLen = 32
10 maxModelLen = 16
11 maxNameLen = 40
12)
13
14// validID reports whether s matches [a-z0-9-]{1,32}.
15func validID(s string) bool {
16 return isSlug(s, maxIDLen)
17}
18
19// validModel reports whether s matches [a-z0-9-]{1,16}.
20func validModel(s string) bool {
21 return isSlug(s, maxModelLen)
22}
23
24// validName reports whether s matches [A-Za-z0-9 '.!-]{1,40}. The charset is
25// deliberately narrow so that a name can be embedded in JSON and markdown
26// without escaping.
27func validName(s string) bool {
28 if len(s) == 0 || len(s) > maxNameLen {
29 return false
30 }
31 for i := 0; i < len(s); i++ {
32 c := s[i]
33 switch {
34 case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9':
35 case c == ' ', c == '\'', c == '.', c == '!', c == '-':
36 default:
37 return false
38 }
39 }
40 return true
41}
42
43// validColor reports whether s is "#rrggbb" with lowercase hex digits.
44func validColor(s string) bool {
45 if len(s) != 7 || s[0] != '#' {
46 return false
47 }
48 for i := 1; i < len(s); i++ {
49 c := s[i]
50 if !(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') {
51 return false
52 }
53 }
54 return true
55}
56
57// validAddress reports whether addr is a valid address in its canonical,
58// lowercase form.
59//
60// Bech32 can also be written in all capitals, and address.IsValid accepts
61// that. To this realm the capitals would be a second key for the same
62// account: a second player record, a second line on a leaderboard, an admin
63// who can never be matched to a caller. Bech32 does not allow mixing cases,
64// so looking at the first character is enough.
65func validAddress(addr address) bool {
66 return addr.IsValid() && addr[0] == 'g'
67}
68
69// isSlug reports whether s is 1 to max characters of [a-z0-9-].
70func isSlug(s string, max int) bool {
71 if len(s) == 0 || len(s) > max {
72 return false
73 }
74 for i := 0; i < len(s); i++ {
75 c := s[i]
76 if !(c >= 'a' && c <= 'z') && !(c >= '0' && c <= '9') && c != '-' {
77 return false
78 }
79 }
80 return true
81}