@@ -9,11 +9,14 @@ import (
9
9
"strings"
10
10
11
11
"code.gitea.io/gitea/modules/log"
12
+
13
+ "gopkg.in/ini.v1"
12
14
)
13
15
14
16
// ExternalMarkupParsers represents the external markup parsers
15
17
var (
16
- ExternalMarkupParsers []MarkupParser
18
+ ExternalMarkupParsers []MarkupParser
19
+ ExternalSanitizerRules []MarkupSanitizerRule
17
20
)
18
21
19
22
// MarkupParser defines the external parser configured in ini
@@ -25,42 +28,115 @@ type MarkupParser struct {
25
28
IsInputFile bool
26
29
}
27
30
31
+ // MarkupSanitizerRule defines the policy for whitelisting attributes on
32
+ // certain elements.
33
+ type MarkupSanitizerRule struct {
34
+ Element string
35
+ AllowAttr string
36
+ Regexp * regexp.Regexp
37
+ }
38
+
28
39
func newMarkup () {
29
- extensionReg := regexp .MustCompile (`\.\w` )
30
40
for _ , sec := range Cfg .Section ("markup" ).ChildSections () {
31
41
name := strings .TrimPrefix (sec .Name (), "markup." )
32
42
if name == "" {
33
43
log .Warn ("name is empty, markup " + sec .Name () + "ignored" )
34
44
continue
35
45
}
36
46
37
- extensions := sec .Key ("FILE_EXTENSIONS" ).Strings ("," )
38
- var exts = make ([]string , 0 , len (extensions ))
39
- for _ , extension := range extensions {
40
- if ! extensionReg .MatchString (extension ) {
41
- log .Warn (sec .Name () + " file extension " + extension + " is invalid. Extension ignored" )
42
- } else {
43
- exts = append (exts , extension )
44
- }
47
+ if name == "sanitizer" {
48
+ newMarkupSanitizer (name , sec )
49
+ } else {
50
+ newMarkupRenderer (name , sec )
45
51
}
52
+ }
53
+ }
54
+
55
+ func newMarkupSanitizer (name string , sec * ini.Section ) {
56
+ haveElement := sec .HasKey ("ELEMENT" )
57
+ haveAttr := sec .HasKey ("ALLOW_ATTR" )
58
+ haveRegexp := sec .HasKey ("REGEXP" )
59
+
60
+ if ! haveElement && ! haveAttr && ! haveRegexp {
61
+ log .Warn ("Skipping empty section: markup.%s." , name )
62
+ return
63
+ }
64
+
65
+ if ! haveElement || ! haveAttr || ! haveRegexp {
66
+ log .Error ("Missing required keys from markup.%s. Must have all three of ELEMENT, ALLOW_ATTR, and REGEXP defined!" , name )
67
+ return
68
+ }
69
+
70
+ elements := sec .Key ("ELEMENT" ).ValueWithShadows ()
71
+ allowAttrs := sec .Key ("ALLOW_ATTR" ).ValueWithShadows ()
72
+ regexps := sec .Key ("REGEXP" ).ValueWithShadows ()
73
+
74
+ if len (elements ) != len (allowAttrs ) ||
75
+ len (elements ) != len (regexps ) ||
76
+ len (allowAttrs ) != len (regexps ) {
77
+ log .Error ("All three keys in markup.%s (ELEMENT, ALLOW_ATTR, REGEXP) must be defined the same number of times! Got %d, %d, and %d respectively." , name , len (elements ), len (allowAttrs ), len (regexps ))
78
+ return
79
+ }
46
80
47
- if len (exts ) == 0 {
48
- log .Warn (sec .Name () + " file extension is empty, markup " + name + " ignored" )
81
+ ExternalSanitizerRules = make ([]MarkupSanitizerRule , 0 , len (elements ))
82
+
83
+ for index , pattern := range regexps {
84
+ if pattern == "" {
85
+ rule := MarkupSanitizerRule {
86
+ Element : elements [index ],
87
+ AllowAttr : allowAttrs [index ],
88
+ Regexp : nil ,
89
+ }
90
+ ExternalSanitizerRules = append (ExternalSanitizerRules , rule )
49
91
continue
50
92
}
51
93
52
- command := sec .Key ("RENDER_COMMAND" ).MustString ("" )
53
- if command == "" {
54
- log .Warn (" RENDER_COMMAND is empty, markup " + name + " ignored" )
94
+ // Validate when parsing the config that this is a valid regular
95
+ // expression. Then we can use regexp.MustCompile(...) later.
96
+ compiled , err := regexp .Compile (pattern )
97
+ if err != nil {
98
+ log .Error ("In module.%s: REGEXP at definition %d failed to compile: %v" , name , index + 1 , err )
55
99
continue
56
100
}
57
101
58
- ExternalMarkupParsers = append (ExternalMarkupParsers , MarkupParser {
59
- Enabled : sec .Key ("ENABLED" ).MustBool (false ),
60
- MarkupName : name ,
61
- FileExtensions : exts ,
62
- Command : command ,
63
- IsInputFile : sec .Key ("IS_INPUT_FILE" ).MustBool (false ),
64
- })
102
+ rule := MarkupSanitizerRule {
103
+ Element : elements [index ],
104
+ AllowAttr : allowAttrs [index ],
105
+ Regexp : compiled ,
106
+ }
107
+ ExternalSanitizerRules = append (ExternalSanitizerRules , rule )
108
+ }
109
+ }
110
+
111
+ func newMarkupRenderer (name string , sec * ini.Section ) {
112
+ extensionReg := regexp .MustCompile (`\.\w` )
113
+
114
+ extensions := sec .Key ("FILE_EXTENSIONS" ).Strings ("," )
115
+ var exts = make ([]string , 0 , len (extensions ))
116
+ for _ , extension := range extensions {
117
+ if ! extensionReg .MatchString (extension ) {
118
+ log .Warn (sec .Name () + " file extension " + extension + " is invalid. Extension ignored" )
119
+ } else {
120
+ exts = append (exts , extension )
121
+ }
122
+ }
123
+
124
+ if len (exts ) == 0 {
125
+ log .Warn (sec .Name () + " file extension is empty, markup " + name + " ignored" )
126
+ return
65
127
}
128
+
129
+ command := sec .Key ("RENDER_COMMAND" ).MustString ("" )
130
+ if command == "" {
131
+ log .Warn (" RENDER_COMMAND is empty, markup " + name + " ignored" )
132
+ return
133
+ }
134
+
135
+ ExternalMarkupParsers = append (ExternalMarkupParsers , MarkupParser {
136
+ Enabled : sec .Key ("ENABLED" ).MustBool (false ),
137
+ MarkupName : name ,
138
+ FileExtensions : exts ,
139
+ Command : command ,
140
+ IsInputFile : sec .Key ("IS_INPUT_FILE" ).MustBool (false ),
141
+ })
66
142
}
0 commit comments