github.com/AndrienkoAleksandr/go@v0.0.19/src/mime/type_unix.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build unix || (js && wasm) || wasip1 6 7 package mime 8 9 import ( 10 "bufio" 11 "os" 12 "strings" 13 ) 14 15 func init() { 16 osInitMime = initMimeUnix 17 } 18 19 // See https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html 20 // for the FreeDesktop Shared MIME-info Database specification. 21 var mimeGlobs = []string{ 22 "/usr/local/share/mime/globs2", 23 "/usr/share/mime/globs2", 24 } 25 26 // Common locations for mime.types files on unix. 27 var typeFiles = []string{ 28 "/etc/mime.types", 29 "/etc/apache2/mime.types", 30 "/etc/apache/mime.types", 31 "/etc/httpd/conf/mime.types", 32 } 33 34 func loadMimeGlobsFile(filename string) error { 35 f, err := os.Open(filename) 36 if err != nil { 37 return err 38 } 39 defer f.Close() 40 41 scanner := bufio.NewScanner(f) 42 for scanner.Scan() { 43 // Each line should be of format: weight:mimetype:glob[:morefields...] 44 fields := strings.Split(scanner.Text(), ":") 45 if len(fields) < 3 || len(fields[0]) < 1 || len(fields[2]) < 3 { 46 continue 47 } else if fields[0][0] == '#' || fields[2][0] != '*' || fields[2][1] != '.' { 48 continue 49 } 50 51 extension := fields[2][1:] 52 if strings.ContainsAny(extension, "?*[") { 53 // Not a bare extension, but a glob. Ignore for now: 54 // - we do not have an implementation for this glob 55 // syntax (translation to path/filepath.Match could 56 // be possible) 57 // - support for globs with weight ordering would have 58 // performance impact to all lookups to support the 59 // rarely seen glob entries 60 // - trying to match glob metacharacters literally is 61 // not useful 62 continue 63 } 64 if _, ok := mimeTypes.Load(extension); ok { 65 // We've already seen this extension. 66 // The file is in weight order, so we keep 67 // the first entry that we see. 68 continue 69 } 70 71 setExtensionType(extension, fields[1]) 72 } 73 if err := scanner.Err(); err != nil { 74 panic(err) 75 } 76 return nil 77 } 78 79 func loadMimeFile(filename string) { 80 f, err := os.Open(filename) 81 if err != nil { 82 return 83 } 84 defer f.Close() 85 86 scanner := bufio.NewScanner(f) 87 for scanner.Scan() { 88 fields := strings.Fields(scanner.Text()) 89 if len(fields) <= 1 || fields[0][0] == '#' { 90 continue 91 } 92 mimeType := fields[0] 93 for _, ext := range fields[1:] { 94 if ext[0] == '#' { 95 break 96 } 97 setExtensionType("."+ext, mimeType) 98 } 99 } 100 if err := scanner.Err(); err != nil { 101 panic(err) 102 } 103 } 104 105 func initMimeUnix() { 106 for _, filename := range mimeGlobs { 107 if err := loadMimeGlobsFile(filename); err == nil { 108 return // Stop checking more files if mimetype database is found. 109 } 110 } 111 112 // Fallback if no system-generated mimetype database exists. 113 for _, filename := range typeFiles { 114 loadMimeFile(filename) 115 } 116 } 117 118 func initMimeForTests() map[string]string { 119 mimeGlobs = []string{""} 120 typeFiles = []string{"testdata/test.types"} 121 return map[string]string{ 122 ".T1": "application/test", 123 ".t2": "text/test; charset=utf-8", 124 ".png": "image/png", 125 } 126 }