Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
mime: support reading shared mime-info database on unix systems
This adds support for reading the FreeDesktop Shared MIME-info Database on Unix systems, if it exists.
It should make lookups work on systems where the mime.types files are not present and
should lead to better mimetype lookup in general. If the shared mimetype database does not exist,
we will fall back to reading mime.types files in common locations.

Related to a bug on Solus bugtracker: https://dev.getsol.us/T9394
This change makes the mime package work on Solus.

Change-Id: If330c22ffe523bf31f7f10807a54fc8858517055
GitHub-Last-Rev: d5fbe8c
GitHub-Pull-Request: #45271
Reviewed-on: https://go-review.googlesource.com/c/go/+/305230
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Tobias Klauser <tobias.klauser@gmail.com>
  • Loading branch information
Jacalz authored and ianlancetaylor committed Apr 12, 2021
1 parent 1b736b3 commit 3e8ba91
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/mime/testdata/test.types.globs2
@@ -0,0 +1,8 @@
# Copyright 2021 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.


# mime package test for globs2
50:document/test:*.t3
50:example/test:*.t4
41 changes: 41 additions & 0 deletions src/mime/type_unix.go
Expand Up @@ -17,13 +17,46 @@ func init() {
osInitMime = initMimeUnix
}

// See https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html
// for the FreeDesktop Shared MIME-info Database specification.
var mimeGlobs = []string{
"/usr/local/share/mime/globs2",
"/usr/share/mime/globs2",
}

// Common locations for mime.types files on unix.
var typeFiles = []string{
"/etc/mime.types",
"/etc/apache2/mime.types",
"/etc/apache/mime.types",
"/etc/httpd/conf/mime.types",
}

func loadMimeGlobsFile(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
// Each line should be of format: weight:mimetype:*.ext
fields := strings.Split(scanner.Text(), ":")
if len(fields) < 3 || len(fields[0]) < 1 || len(fields[2]) < 2 {
continue
} else if fields[0][0] == '#' || fields[2][0] != '*' {
continue
}

setExtensionType(fields[2][1:], fields[1])
}
if err := scanner.Err(); err != nil {
panic(err)
}
return nil
}

func loadMimeFile(filename string) {
f, err := os.Open(filename)
if err != nil {
Expand Down Expand Up @@ -51,12 +84,20 @@ func loadMimeFile(filename string) {
}

func initMimeUnix() {
for _, filename := range mimeGlobs {
if err := loadMimeGlobsFile(filename); err == nil {
return // Stop checking more files if mimetype database is found.
}
}

// Fallback if no system-generated mimetype database exists.
for _, filename := range typeFiles {
loadMimeFile(filename)
}
}

func initMimeForTests() map[string]string {
mimeGlobs = []string{""}
typeFiles = []string{"testdata/test.types"}
return map[string]string{
".T1": "application/test",
Expand Down
39 changes: 39 additions & 0 deletions src/mime/type_unix_test.go
@@ -0,0 +1,39 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris

package mime

import (
"testing"
)

func initMimeUnixTest(t *testing.T) {
err := loadMimeGlobsFile("testdata/test.types.globs2")
if err != nil {
t.Fatal(err)
}

loadMimeFile("testdata/test.types")
}

func TestTypeByExtensionUNIX(t *testing.T) {
initMimeUnixTest(t)
typeTests := map[string]string{
".T1": "application/test",
".t2": "text/test; charset=utf-8",
".t3": "document/test",
".t4": "example/test",
".png": "image/png",
}

for ext, want := range typeTests {
val := TypeByExtension(ext)
if val != want {
t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
}
}
}

0 comments on commit 3e8ba91

Please sign in to comment.