-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
514ead3
commit 408d157
Showing
5 changed files
with
375 additions
and
406 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,48 @@ | ||
// Package mimetype uses magic number signatures to detect and | ||
// to check the MIME type of a file. | ||
// Package mimetype uses magic number signatures to detect the MIME type of a file. | ||
// | ||
// mimetype stores the list of MIME types in a tree structure with | ||
// "application/octet-stream" at the root of the hierarchy. When the detection | ||
// fails to find any result for an input, the MIME type "application/octet-stream" | ||
// is returned. The hierarchy approach minimises the number of checks that need | ||
// to be done on the input and allows for more precise results once the base | ||
// type of file has been identified. | ||
package mimetype | ||
|
||
import ( | ||
"io" | ||
"mime" | ||
"os" | ||
|
||
"github.com/gabriel-vasile/mimetype/internal/matchers" | ||
) | ||
|
||
// Detect returns the MIME type and extension of the provided byte slice. | ||
// | ||
// mime is always a valid MIME type, with application/octet-stream as fallback. | ||
// extension is empty string if detected file format does not have an extension. | ||
func Detect(in []byte) (mime, extension string) { | ||
// Detect returns the MIME type of the provided byte slice. | ||
func Detect(in []byte) (mime *MIME) { | ||
if len(in) == 0 { | ||
return "inode/x-empty", "" | ||
} | ||
n := root.match(in, root) | ||
return n.mime, n.extension | ||
} | ||
|
||
// DetectReader returns the MIME type and extension | ||
// of the byte slice read from the provided reader. | ||
// | ||
// mime is always a valid MIME type, with application/octet-stream as fallback. | ||
// extension is empty string if detection failed with an error or | ||
// detected file format does not have an extension. | ||
func DetectReader(r io.Reader) (mime, extension string, err error) { | ||
in := make([]byte, matchers.ReadLimit) | ||
n, err := r.Read(in) | ||
if err != nil && err != io.EOF { | ||
return root.mime, root.extension, err | ||
} | ||
in = in[:n] | ||
|
||
mime, extension = Detect(in) | ||
return mime, extension, nil | ||
} | ||
|
||
// DetectFile returns the MIME type and extension of the provided file. | ||
// | ||
// mime is always a valid MIME type, with application/octet-stream as fallback. | ||
// extension is empty string if detection failed with an error or | ||
// detected file format does not have an extension. | ||
func DetectFile(file string) (mime, extension string, err error) { | ||
f, err := os.Open(file) | ||
if err != nil { | ||
return root.mime, root.extension, err | ||
} | ||
defer f.Close() | ||
|
||
return DetectReader(f) | ||
} | ||
|
||
// Matches returns whether the MIME type detected from the slice, or any of its | ||
// aliases, is the same as any of the expected MIME types. | ||
// | ||
// MIME type equality test is done on the "type/subtype" sections, ignores any | ||
// optional MIME parameters, ignores any leading and trailing whitespace, | ||
// and is case insensitive. | ||
// Any error returned is related to the parsing of the expected MIME type. | ||
func Matches(in []byte, expectedMimes ...string) (match bool, err error) { | ||
for i := 0; i < len(expectedMimes); i++ { | ||
expectedMimes[i], _, err = mime.ParseMediaType(expectedMimes[i]) | ||
if err != nil { | ||
return false, err | ||
} | ||
return newMIME("inode/x-empty", "", matchers.True) | ||
} | ||
|
||
n := root.match(in, root) | ||
// This parsing is needed because some detected MIME types contain parameters. | ||
found, _, err := mime.ParseMediaType(n.mime) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
for _, expected := range expectedMimes { | ||
if expected == found { | ||
return true, nil | ||
} | ||
for _, alias := range n.aliases { | ||
if alias == expected { | ||
return true, nil | ||
} | ||
} | ||
} | ||
|
||
return false, nil | ||
return root.match(in, root) | ||
} | ||
|
||
// MatchesReader returns whether the MIME type detected from the reader, or any of its | ||
// aliases, is the same as any of the expected MIME types. | ||
// | ||
// MIME type equality test is done on the "type/subtype" sections, ignores any | ||
// optional MIME parameters, ignores any leading and trailing whitespace, | ||
// and is case insensitive. | ||
func MatchesReader(r io.Reader, expectedMimes ...string) (match bool, err error) { | ||
// DetectReader returns the MIME type of the provided reader. | ||
func DetectReader(r io.Reader) (mime *MIME, err error) { | ||
in := make([]byte, matchers.ReadLimit) | ||
n, err := r.Read(in) | ||
if err != nil && err != io.EOF { | ||
return false, err | ||
return root, err | ||
} | ||
in = in[:n] | ||
|
||
return Matches(in, expectedMimes...) | ||
return Detect(in), nil | ||
} | ||
|
||
// MatchesFile returns whether the MIME type detected from the file, or any of its | ||
// aliases, is the same as any of the expected MIME types. | ||
// | ||
// MIME type equality test is done on the "type/subtype" sections, ignores any | ||
// optional MIME parameters, ignores any leading and trailing whitespace, | ||
// and is case insensitive. | ||
func MatchesFile(file string, expectedMimes ...string) (match bool, err error) { | ||
// DetectFile returns the MIME type of the provided file. | ||
func DetectFile(file string) (mime *MIME, err error) { | ||
f, err := os.Open(file) | ||
if err != nil { | ||
return false, err | ||
return root, err | ||
} | ||
defer f.Close() | ||
|
||
return MatchesReader(f, expectedMimes...) | ||
return DetectReader(f) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.