123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- package bluemonday
- import (
- "net/url"
- "regexp"
- "strings"
- )
- type Policy struct {
-
-
-
- initialized bool
-
- allowDocType bool
-
-
- addSpaces bool
-
- requireNoFollow bool
-
-
-
- requireNoFollowFullyQualifiedLinks bool
-
-
-
- addTargetBlankToFullyQualifiedLinks bool
-
- requireParseableURLs bool
-
- allowRelativeURLs bool
-
- elsAndAttrs map[string]map[string]attrPolicy
-
- globalAttrs map[string]attrPolicy
-
-
-
- allowURLSchemes map[string]urlPolicy
-
-
-
-
-
-
-
- setOfElementsAllowedWithoutAttrs map[string]struct{}
- setOfElementsToSkipContent map[string]struct{}
- }
- type attrPolicy struct {
-
-
- regexp *regexp.Regexp
- }
- type attrPolicyBuilder struct {
- p *Policy
- attrNames []string
- regexp *regexp.Regexp
- allowEmpty bool
- }
- type urlPolicy func(url *url.URL) (allowUrl bool)
- func (p *Policy) init() {
- if !p.initialized {
- p.elsAndAttrs = make(map[string]map[string]attrPolicy)
- p.globalAttrs = make(map[string]attrPolicy)
- p.allowURLSchemes = make(map[string]urlPolicy)
- p.setOfElementsAllowedWithoutAttrs = make(map[string]struct{})
- p.setOfElementsToSkipContent = make(map[string]struct{})
- p.initialized = true
- }
- }
- func NewPolicy() *Policy {
- p := Policy{}
- p.addDefaultElementsWithoutAttrs()
- p.addDefaultSkipElementContent()
- return &p
- }
- func (p *Policy) AllowAttrs(attrNames ...string) *attrPolicyBuilder {
- p.init()
- abp := attrPolicyBuilder{
- p: p,
- allowEmpty: false,
- }
- for _, attrName := range attrNames {
- abp.attrNames = append(abp.attrNames, strings.ToLower(attrName))
- }
- return &abp
- }
- func (p *Policy) AllowNoAttrs() *attrPolicyBuilder {
- p.init()
- abp := attrPolicyBuilder{
- p: p,
- allowEmpty: true,
- }
- return &abp
- }
- func (abp *attrPolicyBuilder) AllowNoAttrs() *attrPolicyBuilder {
- abp.allowEmpty = true
- return abp
- }
- func (abp *attrPolicyBuilder) Matching(regex *regexp.Regexp) *attrPolicyBuilder {
- abp.regexp = regex
- return abp
- }
- func (abp *attrPolicyBuilder) OnElements(elements ...string) *Policy {
- for _, element := range elements {
- element = strings.ToLower(element)
- for _, attr := range abp.attrNames {
- if _, ok := abp.p.elsAndAttrs[element]; !ok {
- abp.p.elsAndAttrs[element] = make(map[string]attrPolicy)
- }
- ap := attrPolicy{}
- if abp.regexp != nil {
- ap.regexp = abp.regexp
- }
- abp.p.elsAndAttrs[element][attr] = ap
- }
- if abp.allowEmpty {
- abp.p.setOfElementsAllowedWithoutAttrs[element] = struct{}{}
- if _, ok := abp.p.elsAndAttrs[element]; !ok {
- abp.p.elsAndAttrs[element] = make(map[string]attrPolicy)
- }
- }
- }
- return abp.p
- }
- func (abp *attrPolicyBuilder) Globally() *Policy {
- for _, attr := range abp.attrNames {
- if _, ok := abp.p.globalAttrs[attr]; !ok {
- abp.p.globalAttrs[attr] = attrPolicy{}
- }
- ap := attrPolicy{}
- if abp.regexp != nil {
- ap.regexp = abp.regexp
- }
- abp.p.globalAttrs[attr] = ap
- }
- return abp.p
- }
- func (p *Policy) AllowElements(names ...string) *Policy {
- p.init()
- for _, element := range names {
- element = strings.ToLower(element)
- if _, ok := p.elsAndAttrs[element]; !ok {
- p.elsAndAttrs[element] = make(map[string]attrPolicy)
- }
- }
- return p
- }
- func (p *Policy) RequireNoFollowOnLinks(require bool) *Policy {
- p.requireNoFollow = require
- p.requireParseableURLs = true
- return p
- }
- func (p *Policy) RequireNoFollowOnFullyQualifiedLinks(require bool) *Policy {
- p.requireNoFollowFullyQualifiedLinks = require
- p.requireParseableURLs = true
- return p
- }
- func (p *Policy) AddTargetBlankToFullyQualifiedLinks(require bool) *Policy {
- p.addTargetBlankToFullyQualifiedLinks = require
- p.requireParseableURLs = true
- return p
- }
- func (p *Policy) RequireParseableURLs(require bool) *Policy {
- p.requireParseableURLs = require
- return p
- }
- func (p *Policy) AllowRelativeURLs(require bool) *Policy {
- p.RequireParseableURLs(true)
- p.allowRelativeURLs = require
- return p
- }
- func (p *Policy) AllowURLSchemes(schemes ...string) *Policy {
- p.init()
- p.RequireParseableURLs(true)
- for _, scheme := range schemes {
- scheme = strings.ToLower(scheme)
-
- p.allowURLSchemes[scheme] = nil
- }
- return p
- }
- func (p *Policy) AllowURLSchemeWithCustomPolicy(
- scheme string,
- urlPolicy func(url *url.URL) (allowUrl bool),
- ) *Policy {
- p.init()
- p.RequireParseableURLs(true)
- scheme = strings.ToLower(scheme)
- p.allowURLSchemes[scheme] = urlPolicy
- return p
- }
- func (p *Policy) AllowDocType(allow bool) *Policy {
- p.allowDocType = allow
- return p
- }
- func (p *Policy) AddSpaceWhenStrippingTag(allow bool) *Policy {
- p.addSpaces = allow
- return p
- }
- func (p *Policy) SkipElementsContent(names ...string) *Policy {
- p.init()
- for _, element := range names {
- element = strings.ToLower(element)
- if _, ok := p.setOfElementsToSkipContent[element]; !ok {
- p.setOfElementsToSkipContent[element] = struct{}{}
- }
- }
- return p
- }
- func (p *Policy) AllowElementsContent(names ...string) *Policy {
- p.init()
- for _, element := range names {
- delete(p.setOfElementsToSkipContent, strings.ToLower(element))
- }
- return p
- }
- func (p *Policy) addDefaultElementsWithoutAttrs() {
- p.init()
- p.setOfElementsAllowedWithoutAttrs["abbr"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["acronym"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["article"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["aside"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["audio"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["b"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["bdi"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["blockquote"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["body"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["br"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["button"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["canvas"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["caption"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["cite"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["code"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["col"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["colgroup"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["datalist"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["dd"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["del"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["details"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["dfn"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["div"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["dl"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["dt"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["em"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["fieldset"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["figcaption"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["figure"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["footer"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h1"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h2"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h3"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h4"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h5"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["h6"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["head"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["header"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["hgroup"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["hr"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["html"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["i"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["ins"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["kbd"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["li"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["mark"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["nav"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["ol"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["optgroup"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["option"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["p"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["pre"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["q"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["rp"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["rt"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["ruby"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["s"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["samp"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["section"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["select"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["small"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["span"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["strike"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["strong"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["style"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["sub"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["summary"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["sup"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["svg"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["table"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["tbody"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["td"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["textarea"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["tfoot"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["th"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["thead"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["title"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["time"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["tr"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["tt"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["u"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["ul"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["var"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["video"] = struct{}{}
- p.setOfElementsAllowedWithoutAttrs["wbr"] = struct{}{}
- }
- func (p *Policy) addDefaultSkipElementContent() {
- p.init()
- p.setOfElementsToSkipContent["frame"] = struct{}{}
- p.setOfElementsToSkipContent["frameset"] = struct{}{}
- p.setOfElementsToSkipContent["iframe"] = struct{}{}
- p.setOfElementsToSkipContent["noembed"] = struct{}{}
- p.setOfElementsToSkipContent["noframes"] = struct{}{}
- p.setOfElementsToSkipContent["noscript"] = struct{}{}
- p.setOfElementsToSkipContent["nostyle"] = struct{}{}
- p.setOfElementsToSkipContent["object"] = struct{}{}
- p.setOfElementsToSkipContent["script"] = struct{}{}
- p.setOfElementsToSkipContent["style"] = struct{}{}
- p.setOfElementsToSkipContent["title"] = struct{}{}
- }
|