123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- package bluemonday
- import (
- "encoding/base64"
- "net/url"
- "regexp"
- )
- var (
-
-
- CellAlign = regexp.MustCompile(`(?i)^(center|justify|left|right|char)$`)
-
-
- CellVerticalAlign = regexp.MustCompile(`(?i)^(baseline|bottom|middle|top)$`)
-
-
- Direction = regexp.MustCompile(`(?i)^(rtl|ltr)$`)
-
-
- ImageAlign = regexp.MustCompile(
- `(?i)^(left|right|top|texttop|middle|absmiddle|baseline|bottom|absbottom)$`,
- )
-
-
-
- Integer = regexp.MustCompile(`^[0-9]+$`)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ISO8601 = regexp.MustCompile(
- `^[0-9]{4}(-[0-9]{2}(-[0-9]{2}([ T][0-9]{2}(:[0-9]{2}){1,2}(.[0-9]{1,6})` +
- `?Z?([\+-][0-9]{2}:[0-9]{2})?)?)?)?$`,
- )
-
-
-
- ListType = regexp.MustCompile(`(?i)^(circle|disc|square|a|A|i|I|1)$`)
-
-
-
-
- SpaceSeparatedTokens = regexp.MustCompile(`^([\s\p{L}\p{N}_-]+)$`)
-
-
- Number = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$`)
-
-
-
- NumberOrPercent = regexp.MustCompile(`^[0-9]+[%]?$`)
-
-
-
- Paragraph = regexp.MustCompile(`^[\p{L}\p{N}\s\-_',\[\]!\./\\\(\)]*$`)
-
-
-
-
-
- dataURIImagePrefix = regexp.MustCompile(
- `^image/(gif|jpeg|png|webp);base64,`,
- )
- )
- func (p *Policy) AllowStandardURLs() {
-
- p.RequireParseableURLs(true)
-
- p.AllowRelativeURLs(true)
-
- p.AllowURLSchemes("mailto", "http", "https")
-
-
- p.RequireNoFollowOnLinks(true)
- }
- func (p *Policy) AllowStandardAttributes() {
-
-
- p.AllowAttrs("dir").Matching(Direction).Globally()
- p.AllowAttrs(
- "lang",
- ).Matching(regexp.MustCompile(`[a-zA-Z]{2,20}`)).Globally()
-
-
-
-
-
- p.AllowAttrs("id").Matching(
- regexp.MustCompile(`[a-zA-Z0-9\:\-_\.]+`),
- ).Globally()
-
- p.AllowAttrs("title").Matching(Paragraph).Globally()
- }
- func (p *Policy) AllowStyling() {
-
- p.AllowAttrs("class").Matching(SpaceSeparatedTokens).Globally()
- }
- func (p *Policy) AllowImages() {
-
- p.AllowAttrs("align").Matching(ImageAlign).OnElements("img")
- p.AllowAttrs("alt").Matching(Paragraph).OnElements("img")
- p.AllowAttrs("height", "width").Matching(NumberOrPercent).OnElements("img")
-
- p.AllowStandardURLs()
- p.AllowAttrs("src").OnElements("img")
- }
- func (p *Policy) AllowDataURIImages() {
-
- p.RequireParseableURLs(true)
-
- p.AllowURLSchemeWithCustomPolicy(
- "data",
- func(url *url.URL) (allowUrl bool) {
- if url.RawQuery != "" || url.Fragment != "" {
- return false
- }
- matched := dataURIImagePrefix.FindString(url.Opaque)
- if matched == "" {
- return false
- }
- _, err := base64.StdEncoding.DecodeString(url.Opaque[len(matched):])
- if err != nil {
- return false
- }
- return true
- },
- )
- }
- func (p *Policy) AllowLists() {
-
- p.AllowAttrs("type").Matching(ListType).OnElements("ol", "ul")
-
- p.AllowAttrs("type").Matching(ListType).OnElements("li")
- p.AllowAttrs("value").Matching(Integer).OnElements("li")
-
- p.AllowElements("dl", "dt", "dd")
- }
- func (p *Policy) AllowTables() {
-
- p.AllowAttrs("height", "width").Matching(NumberOrPercent).OnElements("table")
- p.AllowAttrs("summary").Matching(Paragraph).OnElements("table")
-
- p.AllowElements("caption")
-
- p.AllowAttrs("align").Matching(CellAlign).OnElements("col", "colgroup")
- p.AllowAttrs("height", "width").Matching(
- NumberOrPercent,
- ).OnElements("col", "colgroup")
- p.AllowAttrs("span").Matching(Integer).OnElements("colgroup", "col")
- p.AllowAttrs("valign").Matching(
- CellVerticalAlign,
- ).OnElements("col", "colgroup")
-
- p.AllowAttrs("align").Matching(CellAlign).OnElements("thead", "tr")
- p.AllowAttrs("valign").Matching(CellVerticalAlign).OnElements("thead", "tr")
-
- p.AllowAttrs("abbr").Matching(Paragraph).OnElements("td", "th")
- p.AllowAttrs("align").Matching(CellAlign).OnElements("td", "th")
- p.AllowAttrs("colspan", "rowspan").Matching(Integer).OnElements("td", "th")
- p.AllowAttrs("headers").Matching(
- SpaceSeparatedTokens,
- ).OnElements("td", "th")
- p.AllowAttrs("height", "width").Matching(
- NumberOrPercent,
- ).OnElements("td", "th")
- p.AllowAttrs(
- "scope",
- ).Matching(
- regexp.MustCompile(`(?i)(?:row|col)(?:group)?`),
- ).OnElements("td", "th")
- p.AllowAttrs("valign").Matching(CellVerticalAlign).OnElements("td", "th")
- p.AllowAttrs("nowrap").Matching(
- regexp.MustCompile(`(?i)|nowrap`),
- ).OnElements("td", "th")
-
- p.AllowAttrs("align").Matching(CellAlign).OnElements("tbody", "tfoot")
- p.AllowAttrs("valign").Matching(
- CellVerticalAlign,
- ).OnElements("tbody", "tfoot")
- }
|