Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of mime; | 5 library mime.mime_type; |
| 6 | 6 |
| 7 import 'default_extension_map.dart'; | |
| 8 import 'magic_number.dart'; | |
| 7 | 9 |
| 8 final MimeTypeResolver _globalResolver = new MimeTypeResolver(); | 10 final MimeTypeResolver _globalResolver = new MimeTypeResolver(); |
| 9 | 11 |
| 10 /** | 12 /** |
| 11 * The maximum number of bytes needed, to match all default magic-numbers. | 13 * The maximum number of bytes needed, to match all default magic-numbers. |
| 12 */ | 14 */ |
| 13 int get defaultMagicNumbersMaxLength => _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; | 15 // NOTE: this is not formatted AS_A_CONST to avoid a breaking change |
| 16 const int defaultMagicNumbersMaxLength = 12; | |
|
Anders Johnsen
2014/05/13 09:16:22
Thinking about it, this should really not be publi
kevmoo
2014/05/13 17:48:39
Let's talk about how to expose this. Perhaps we ca
Anders Johnsen
2014/05/14 07:36:07
But this entry is not useful for the user _at all_
| |
| 14 | 17 |
| 15 /** | 18 /** |
| 16 * Extract the extension from [path] and use that for MIME-type lookup, using | 19 * Extract the extension from [path] and use that for MIME-type lookup, using |
| 17 * the default extension map. | 20 * the default extension map. |
| 18 * | 21 * |
| 19 * If no matching MIME-type was found, `null` is returned. | 22 * If no matching MIME-type was found, `null` is returned. |
| 20 * | 23 * |
| 21 * If [headerBytes] is present, a match for known magic-numbers will be | 24 * If [headerBytes] is present, a match for known magic-numbers will be |
| 22 * performed first. This allows the correct mime-type to be found, even though | 25 * performed first. This allows the correct mime-type to be found, even though |
| 23 * a file have been saved using the wrong file-name extension. If less than | 26 * a file have been saved using the wrong file-name extension. If less than |
| 24 * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't | 27 * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't |
| 25 * be matched against. | 28 * be matched against. |
| 26 */ | 29 */ |
| 27 String lookupMimeType(String path, {List<int> headerBytes}) => | 30 String lookupMimeType(String path, {List<int> headerBytes}) => |
| 28 _globalResolver.lookup(path, headerBytes: headerBytes); | 31 _globalResolver.lookup(path, headerBytes: headerBytes); |
| 29 | 32 |
| 30 /** | 33 /** |
| 31 * MIME-type resolver class, used to customize the lookup of mime-types. | 34 * MIME-type resolver class, used to customize the lookup of mime-types. |
| 32 */ | 35 */ |
| 33 class MimeTypeResolver { | 36 class MimeTypeResolver { |
| 34 final Map<String, String> _extensionMap = {}; | 37 final Map<String, String> _extensionMap = {}; |
| 35 final List<_MagicNumber> _magicNumbers = []; | 38 final List<MagicNumber> _magicNumbers = []; |
| 36 final bool _useDefault; | 39 final bool _useDefault; |
| 37 int _magicNumbersMaxLength; | 40 int _magicNumbersMaxLength; |
| 38 | 41 |
| 39 /** | 42 /** |
| 40 * Create a new empty [MimeTypeResolver]. | 43 * Create a new empty [MimeTypeResolver]. |
| 41 */ | 44 */ |
| 42 MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; | 45 MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; |
| 43 | 46 |
| 44 /** | 47 /** |
| 45 * Create a new [MimeTypeResolver] containing the default scope. | 48 * Create a new [MimeTypeResolver] containing the default scope. |
| 46 */ | 49 */ |
| 47 MimeTypeResolver() : | 50 MimeTypeResolver() : |
| 48 _useDefault = true, | 51 _useDefault = true, |
| 49 _magicNumbersMaxLength = _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; | 52 _magicNumbersMaxLength = defaultMagicNumbersMaxLength; |
| 50 | 53 |
| 51 /** | 54 /** |
| 52 * Get the maximum number of bytes required to match all magic numbers, when | 55 * Get the maximum number of bytes required to match all magic numbers, when |
| 53 * performing [lookup] with headerBytes present. | 56 * performing [lookup] with headerBytes present. |
| 54 */ | 57 */ |
| 55 int get magicNumbersMaxLength => _magicNumbersMaxLength; | 58 int get magicNumbersMaxLength => _magicNumbersMaxLength; |
| 56 | 59 |
| 57 /** | 60 /** |
| 58 * Extract the extension from [path] and use that for MIME-type lookup. | 61 * Extract the extension from [path] and use that for MIME-type lookup. |
| 59 * | 62 * |
| 60 * If no matching MIME-type was found, `null` is returned. | 63 * If no matching MIME-type was found, `null` is returned. |
| 61 * | 64 * |
| 62 * If [headerBytes] is present, a match for known magic-numbers will be | 65 * If [headerBytes] is present, a match for known magic-numbers will be |
| 63 * performed first. This allows the correct mime-type to be found, even though | 66 * performed first. This allows the correct mime-type to be found, even though |
| 64 * a file have been saved using the wrong file-name extension. If less than | 67 * a file have been saved using the wrong file-name extension. If less than |
| 65 * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't | 68 * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't |
| 66 * be matched against. | 69 * be matched against. |
| 67 */ | 70 */ |
| 68 String lookup(String path, {List<int> headerBytes}) { | 71 String lookup(String path, {List<int> headerBytes}) { |
| 69 String result; | 72 String result; |
| 70 if (headerBytes != null) { | 73 if (headerBytes != null) { |
| 71 result = _matchMagic(headerBytes, _magicNumbers); | 74 result = _matchMagic(headerBytes, _magicNumbers); |
| 72 if (result != null) return result; | 75 if (result != null) return result; |
| 73 if (_useDefault) { | 76 if (_useDefault) { |
| 74 result = _matchMagic(headerBytes, _DEFAULT_MAGIC_NUMBERS); | 77 result = _matchMagic(headerBytes, DEFAULT_MAGIC_NUMBERS); |
| 75 if (result != null) return result; | 78 if (result != null) return result; |
| 76 } | 79 } |
| 77 } | 80 } |
| 78 var ext = _ext(path); | 81 var ext = _ext(path); |
| 79 result = _extensionMap[ext]; | 82 result = _extensionMap[ext]; |
| 80 if (result != null) return result; | 83 if (result != null) return result; |
| 81 if (_useDefault) { | 84 if (_useDefault) { |
| 82 result = _DEFAULT_EXTENSION_MAP[ext]; | 85 result = DEFAULT_EXTENSION_MAP[ext]; |
| 83 if (result != null) return result; | 86 if (result != null) return result; |
| 84 } | 87 } |
| 85 return null; | 88 return null; |
| 86 } | 89 } |
| 87 | 90 |
| 88 /** | 91 /** |
| 89 * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] | 92 * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] |
| 90 * is already present in the [MimeTypeResolver], it'll be overwritten. | 93 * is already present in the [MimeTypeResolver], it'll be overwritten. |
| 91 */ | 94 */ |
| 92 void addExtension(String extension, String mimeType) { | 95 void addExtension(String extension, String mimeType) { |
| 93 _extensionMap[extension] = mimeType; | 96 _extensionMap[extension] = mimeType; |
| 94 } | 97 } |
| 95 | 98 |
| 96 /** | 99 /** |
| 97 * Add a new magic-number mapping to the [MimeTypeResolver]. | 100 * Add a new magic-number mapping to the [MimeTypeResolver]. |
| 98 * | 101 * |
| 99 * If [mask] is present,the [mask] is used to only perform matching on | 102 * If [mask] is present,the [mask] is used to only perform matching on |
| 100 * selective bits. The [mask] must have the same length as [bytes]. | 103 * selective bits. The [mask] must have the same length as [bytes]. |
| 101 */ | 104 */ |
| 102 void addMagicNumber(List<int> bytes, String mimeType, {List<int> mask}) { | 105 void addMagicNumber(List<int> bytes, String mimeType, {List<int> mask}) { |
| 103 if (mask != null && bytes.length != mask.length) { | 106 if (mask != null && bytes.length != mask.length) { |
| 104 throw new ArgumentError('Bytes and mask are of different lengths'); | 107 throw new ArgumentError('Bytes and mask are of different lengths'); |
| 105 } | 108 } |
| 106 if (bytes.length > _magicNumbersMaxLength) { | 109 if (bytes.length > _magicNumbersMaxLength) { |
| 107 _magicNumbersMaxLength = bytes.length; | 110 _magicNumbersMaxLength = bytes.length; |
| 108 } | 111 } |
| 109 _magicNumbers.add(new _MagicNumber(mimeType, bytes, mask: mask)); | 112 _magicNumbers.add(new MagicNumber(mimeType, bytes, mask: mask)); |
| 110 } | 113 } |
| 111 | 114 |
| 112 static String _matchMagic(List<int> headerBytes, | 115 static String _matchMagic(List<int> headerBytes, |
| 113 List<_MagicNumber> magicNumbers) { | 116 List<MagicNumber> magicNumbers) { |
| 114 for (var mn in magicNumbers) { | 117 for (var mn in magicNumbers) { |
| 115 if (mn.matches(headerBytes)) return mn.mimeType; | 118 if (mn.matches(headerBytes)) return mn.mimeType; |
| 116 } | 119 } |
| 117 return null; | 120 return null; |
| 118 } | 121 } |
| 119 | 122 |
| 120 static String _ext(String path) { | 123 static String _ext(String path) { |
| 121 int index = path.lastIndexOf('.'); | 124 int index = path.lastIndexOf('.'); |
| 122 if (index < 0 || index + 1 >= path.length) return path; | 125 if (index < 0 || index + 1 >= path.length) return path; |
| 123 return path.substring(index + 1).toLowerCase(); | 126 return path.substring(index + 1).toLowerCase(); |
| 124 } | 127 } |
| 125 } | 128 } |
| 126 | 129 |
| OLD | NEW |