Chromium Code Reviews| Index: pkg/mime/lib/src/mime_type.dart |
| diff --git a/pkg/mime/lib/src/mime_type.dart b/pkg/mime/lib/src/mime_type.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f64ae4d8b5c8611a7e52fea6d7a4b2f2bcff2bd5 |
| --- /dev/null |
| +++ b/pkg/mime/lib/src/mime_type.dart |
| @@ -0,0 +1,117 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +part of mime_type; |
| + |
| + |
| +MimeTypeResolver _globalResolver = new MimeTypeResolver(); |
| + |
| +/** |
| + * Extract the extension from [path] and use that for MIME-type lookup, using |
| + * the default extension map. |
|
Søren Gjesse
2013/06/24 11:02:55
What happens if the extension is not found?
Anders Johnsen
2013/06/24 11:22:19
Done.
|
| + * |
| + * If [headerBytes] is present, a match for known magic-numbers will be |
| + * performed first. This allows the correct mime-type to be found, even though |
| + * a file have been saved using the wrong file-name extension. |
|
Søren Gjesse
2013/06/24 11:02:55
Please add some information on the number of bytes
Anders Johnsen
2013/06/24 11:22:19
Done.
|
| + */ |
| +String lookupMimeType(String path, |
|
Søren Gjesse
2013/06/24 11:02:55
How about moving this to a static method on the Mi
Anders Johnsen
2013/06/24 11:22:19
I've seen from other libraries and code that peopl
|
| + {List<int> headerBytes}) |
| + => _globalResolver.lookup(path, headerBytes: headerBytes); |
| + |
| + |
| +/** |
| + * MIME-type resolver class, used to customize the lookup of mime-types. |
| + */ |
| +class MimeTypeResolver { |
|
Søren Gjesse
2013/06/24 11:02:55
Maybe add static getter for the global resolver.
Anders Johnsen
2013/06/24 11:22:19
As discussed offline, I prefer the global one to b
|
| + final Map<String, String> _extensionMap = {}; |
| + final List<_MagicNumber> _magicNumbers = []; |
| + bool _useDefault; |
| + int _magicNumbersMaxLength; |
| + |
| + /** |
| + * Create a new empty [MimeTypeResolver]. |
| + */ |
| + MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; |
| + |
| + /** |
| + * Create a new [MimeTypeResolver] containing the default scope. |
| + */ |
| + MimeTypeResolver() : |
| + _useDefault = true, |
| + _magicNumbersMaxLength = _defaultMagicNumbersMaxLength; |
| + |
| + /** |
| + * Get the maximum number of bytes required to match all magic numbers, when |
| + * performing [lookup] with headerBytes present. |
| + */ |
| + int get magicNumbersMaxLength => _magicNumbersMaxLength; |
| + |
| + /** |
| + * Extract the extension from [path] and use that for MIME-type lookup. |
| + * |
| + * If [headerBytes] is present, a match for known magic-numbers will be |
| + * performed first. This allows the correct mime-type to be found, even though |
| + * a file have been saved using the wrong file-name extension. |
| + */ |
| + String lookup(String path, |
| + {List<int> headerBytes}) { |
| + String result; |
| + if (headerBytes != null) { |
| + result =_matchMagic(headerBytes, _magicNumbers); |
| + if (result != null) return result; |
| + if (_useDefault) { |
| + result =_matchMagic(headerBytes, _defaultMagicNumbers); |
| + if (result != null) return result; |
| + } |
| + } |
| + var ext = _ext(path); |
| + result = _extensionMap[ext]; |
| + if (result != null) return result; |
| + if (_useDefault) { |
| + result = _defaultExtensionMap[ext]; |
| + if (result != null) return result; |
| + } |
| + return '<unknown>'; |
| + } |
| + |
| + /** |
| + * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] |
| + * is already present in the [MimeTypeResolver], it'll be overwritten. |
| + */ |
| + void addExtension(String extension, String mimeType) { |
| + _extensionMap[extension] = mimeType; |
| + } |
| + |
| + /** |
| + * Add a new magic-number mapping to the [MimeTypeResolver]. |
| + * |
| + * If [mask] is present,the [mask] is used to only perform matching on |
| + * selective bytes. The [mask] must have the same length as [bytes], and the |
| + * matching will be done for any non-0 value in mask. |
| + */ |
| + void addMagicNumber(List<int> bytes, String mimeType, {List<int> mask}) { |
| + if (mask != null && bytes.length != mask.length) { |
| + throw new ArgumentError('Bytes and mask are of different lengths'); |
| + } |
| + if (bytes.length > _magicNumbersMaxLength) { |
| + _magicNumbersMaxLength = bytes.length; |
| + } |
| + _MagicNumber.add(new _MagicNumber(bytes, mimeType, mask: mask)); |
| + } |
| + |
| + static String _matchMagic(List<int> headerBytes, |
| + List<_MagicNumber> magicNumbers) { |
| + for (var mn in magicNumbers) { |
| + if (mn.matches(headerBytes)) return mn.mimeType; |
| + } |
| + return null; |
| + } |
| + |
| + static String _ext(String path) { |
| + int index = path.lastIndexOf('.'); |
| + if (index < 0 || index + 1 >= path.length) return path; |
| + return path.substring(index + 1).toLowerCase(); |
| + } |
| +} |
| + |