migration_media.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package storage
  2. import (
  3. "bytes"
  4. "net/http"
  5. )
  6. // detectMediaType trusts bytes rather than the filename or multipart MIME header.
  7. func detectMediaType(data []byte) string {
  8. switch http.DetectContentType(data) {
  9. case "image/jpeg", "image/png", "image/gif", "image/webp":
  10. return http.DetectContentType(data)
  11. }
  12. if isWebM(data) {
  13. return "video/webm"
  14. }
  15. return ""
  16. }
  17. // isWebM parses the EBML header and requires an explicit WebM DocType. Merely
  18. // finding the word "webm" or an EBML magic number also admits Matroska files.
  19. func isWebM(data []byte) bool {
  20. if len(data) < 5 || !bytes.Equal(data[:4], []byte{0x1a, 0x45, 0xdf, 0xa3}) {
  21. return false
  22. }
  23. size, n, ok := ebmlSize(data[4:])
  24. if !ok || size > uint64(len(data)-4-n) {
  25. return false
  26. }
  27. header := data[4+n : 4+n+int(size)]
  28. found := false
  29. for len(header) > 0 {
  30. // EBML element IDs retain their leading marker bit.
  31. _, idLen, valid := ebmlSize(header)
  32. if !valid || idLen > 4 || len(header) <= idLen {
  33. return false
  34. }
  35. id := header[:idLen]
  36. length, lenLen, valid := ebmlSize(header[idLen:])
  37. if !valid || length > uint64(len(header)-idLen-lenLen) {
  38. return false
  39. }
  40. value := header[idLen+lenLen : idLen+lenLen+int(length)]
  41. if bytes.Equal(id, []byte{0x42, 0x82}) {
  42. if found || !bytes.Equal(value, []byte("webm")) {
  43. return false
  44. }
  45. found = true
  46. }
  47. header = header[idLen+lenLen+int(length):]
  48. }
  49. return found
  50. }
  51. // ebmlSize reads a bounded EBML variable-length integer. Unknown sizes are
  52. // rejected because the header and its children must have finite lengths.
  53. func ebmlSize(b []byte) (uint64, int, bool) {
  54. if len(b) == 0 || b[0] == 0 {
  55. return 0, 0, false
  56. }
  57. mask, n := byte(0x80), 1
  58. for b[0]&mask == 0 {
  59. mask >>= 1
  60. n++
  61. }
  62. if n > len(b) {
  63. return 0, 0, false
  64. }
  65. value := uint64(b[0] & (mask - 1))
  66. for _, v := range b[1:n] {
  67. value = value<<8 | uint64(v)
  68. }
  69. if value == (uint64(1)<<(7*n))-1 {
  70. return 0, 0, false
  71. }
  72. return value, n, true
  73. }