svg.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package imagemeta
  2. import (
  3. "bytes"
  4. "encoding/xml"
  5. "fmt"
  6. "io"
  7. "strings"
  8. "sync/atomic"
  9. "golang.org/x/text/encoding/charmap"
  10. )
  11. var maxSvgBytes int64 = 32 * 1024
  12. type svgHeader struct {
  13. XMLName xml.Name
  14. }
  15. func xmlCharsetReader(charset string, input io.Reader) (io.Reader, error) {
  16. if strings.EqualFold(charset, "iso-8859-1") {
  17. return charmap.ISO8859_1.NewDecoder().Reader(input), nil
  18. }
  19. return nil, fmt.Errorf("Unknown SVG charset: %s", charset)
  20. }
  21. func SetMaxSvgCheckRead(n int) {
  22. atomic.StoreInt64(&maxSvgBytes, int64(n))
  23. }
  24. func IsSVG(r io.Reader) (bool, error) {
  25. maxBytes := int(atomic.LoadInt64(&maxSvgBytes))
  26. var h svgHeader
  27. buf := make([]byte, 0, maxBytes)
  28. b := make([]byte, 1024)
  29. rr := bytes.NewReader(buf)
  30. for {
  31. n, err := r.Read(b)
  32. if err != nil && err != io.EOF {
  33. return false, err
  34. }
  35. if n <= 0 {
  36. return false, nil
  37. }
  38. buf = append(buf, b[:n]...)
  39. rr.Reset(buf)
  40. dec := xml.NewDecoder(rr)
  41. dec.Strict = false
  42. dec.CharsetReader = xmlCharsetReader
  43. if dec.Decode(&h); h.XMLName.Local == "svg" {
  44. return true, nil
  45. }
  46. if len(buf) >= maxBytes {
  47. break
  48. }
  49. }
  50. return false, nil
  51. }