package util import ( "fmt" "html/template" "log" "net/url" "strings" "github.com/gomarkdown/markdown" "github.com/microcosm-cc/bluemonday" // "errors" ) /* util.Eout example invocations if err != nil { return util.Eout(err, "reading data") } if err = util.Eout(err, "reading data"); err != nil { return nil, err } */ type ErrorDescriber struct { environ string // the basic context that is potentially generating errors (like a GetThread function, the environ would be "get thread") } // parametrize Eout/Check such that error messages contain a defined context/environ func Describe(environ string) ErrorDescriber { return ErrorDescriber{environ} } func (ed ErrorDescriber) Eout(err error, msg string, args ...interface{}) error { msg = fmt.Sprintf("%s: %s", ed.environ, msg) return Eout(err, msg, args...) } func (ed ErrorDescriber) Check(err error, msg string, args ...interface{}) { msg = fmt.Sprintf("%s: %s", ed.environ, msg) Check(err, msg, args...) } // format all errors consistently, and provide context for the error using the string `msg` func Eout(err error, msg string, args ...interface{}) error { if err != nil { // received an invocation of e.g. format: // Eout(err, "reading data for %s and %s", "database item", "weird user") if len(args) > 0 { return fmt.Errorf("%s (%w)", fmt.Sprintf(msg, args...), err) } return fmt.Errorf("%s (%w)", msg, err) } return nil } func Check(err error, msg string, args ...interface{}) { if len(args) > 0 { err = Eout(err, msg, args...) } else { err = Eout(err, msg) } if err != nil { log.Fatalln(err) } } func Contains(slice []string, s string) bool { for _, item := range slice { if item == s { return true } } return false } var contentGuardian = bluemonday.UGCPolicy() var strictContentGuardian = bluemonday.StrictPolicy() // Turns Markdown input into HTML func Markup(md template.HTML) template.HTML { mdBytes := []byte(string(md)) // fix newlines mdBytes = markdown.NormalizeNewlines(mdBytes) maybeUnsafeHTML := markdown.ToHTML(mdBytes, nil, nil) // guard against malicious code being embedded html := contentGuardian.SanitizeBytes(maybeUnsafeHTML) return template.HTML(html) } func SanitizeStringStrict(s string) string { return strictContentGuardian.Sanitize(s) } // make a string be suitable for use as part of a url func SanitizeURL(input string) string { input = strings.ReplaceAll(input, " ", "-") input = url.PathEscape(input) // TODO(2022-01-08): evaluate use of strict content guardian? return strings.ToLower(input) }