Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Detecting mime types is a tricky business because we need to balance | 5 // Detecting mime types is a tricky business because we need to balance |
| 6 // compatibility concerns with security issues. Here is a survey of how other | 6 // compatibility concerns with security issues. Here is a survey of how other |
| 7 // browsers behave and then a description of how we intend to behave. | 7 // browsers behave and then a description of how we intend to behave. |
| 8 // | 8 // |
| 9 // HTML payload, no Content-Type header: | 9 // HTML payload, no Content-Type header: |
| 10 // * IE 7: Render as HTML | 10 // * IE 7: Render as HTML |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 MAGIC_NUMBER("text/plain", ">From") | 139 MAGIC_NUMBER("text/plain", ">From") |
| 140 // Chrome specific | 140 // Chrome specific |
| 141 MAGIC_NUMBER("application/x-gzip", "\x1F\x8B\x08") | 141 MAGIC_NUMBER("application/x-gzip", "\x1F\x8B\x08") |
| 142 MAGIC_NUMBER("audio/x-pn-realaudio", "\x2E\x52\x4D\x46") | 142 MAGIC_NUMBER("audio/x-pn-realaudio", "\x2E\x52\x4D\x46") |
| 143 MAGIC_NUMBER("video/x-ms-asf", | 143 MAGIC_NUMBER("video/x-ms-asf", |
| 144 "\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C") | 144 "\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C") |
| 145 MAGIC_NUMBER("image/tiff", "I I") | 145 MAGIC_NUMBER("image/tiff", "I I") |
| 146 MAGIC_NUMBER("image/tiff", "II*") | 146 MAGIC_NUMBER("image/tiff", "II*") |
| 147 MAGIC_NUMBER("image/tiff", "MM\x00*") | 147 MAGIC_NUMBER("image/tiff", "MM\x00*") |
| 148 MAGIC_NUMBER("audio/mpeg", "ID3") | 148 MAGIC_NUMBER("audio/mpeg", "ID3") |
| 149 MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 ") | |
| 150 MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3") | |
| 149 // TODO(abarth): we don't handle partial byte matches yet | 151 // TODO(abarth): we don't handle partial byte matches yet |
| 150 // MAGIC_NUMBER("video/mpeg", "\x00\x00\x01\xB") | 152 // MAGIC_NUMBER("video/mpeg", "\x00\x00\x01\xB") |
| 151 // MAGIC_NUMBER("audio/mpeg", "\xFF\xE") | 153 // MAGIC_NUMBER("audio/mpeg", "\xFF\xE") |
| 152 // MAGIC_NUMBER("audio/mpeg", "\xFF\xF") | 154 // MAGIC_NUMBER("audio/mpeg", "\xFF\xF") |
| 153 MAGIC_NUMBER("application/zip", "PK\x03\x04") | 155 MAGIC_NUMBER("application/zip", "PK\x03\x04") |
| 154 MAGIC_NUMBER("application/x-rar-compressed", "Rar!\x1A\x07\x00") | 156 MAGIC_NUMBER("application/x-rar-compressed", "Rar!\x1A\x07\x00") |
| 155 MAGIC_NUMBER("application/x-msmetafile", "\xD7\xCD\xC6\x9A") | 157 MAGIC_NUMBER("application/x-msmetafile", "\xD7\xCD\xC6\x9A") |
| 156 MAGIC_NUMBER("application/octet-stream", "MZ") // EXE | 158 MAGIC_NUMBER("application/octet-stream", "MZ") // EXE |
| 157 // Sniffing for Flash: | 159 // Sniffing for Flash: |
| 158 // | 160 // |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 }; | 210 }; |
| 209 | 211 |
| 210 static scoped_refptr<base::Histogram> UMASnifferHistogramGet(const char* name, | 212 static scoped_refptr<base::Histogram> UMASnifferHistogramGet(const char* name, |
| 211 int array_size) { | 213 int array_size) { |
| 212 scoped_refptr<base::Histogram> counter = | 214 scoped_refptr<base::Histogram> counter = |
| 213 base::LinearHistogram::FactoryGet(name, 1, array_size - 1, array_size, | 215 base::LinearHistogram::FactoryGet(name, 1, array_size - 1, array_size, |
| 214 base::Histogram::kUmaTargetedHistogramFlag); | 216 base::Histogram::kUmaTargetedHistogramFlag); |
| 215 return counter; | 217 return counter; |
| 216 } | 218 } |
| 217 | 219 |
| 220 static bool MagicCmp(const char* magic_entry, const char* content, size_t len) { | |
| 221 bool same = true; | |
| 222 while (len && same) { | |
| 223 if (!*content && !magic_entry) { | |
|
Tom Finegan
2011/01/11 18:51:11
I think you want !*magic_entry here; at least if y
fbarchard1
2011/01/11 19:20:11
Done.
| |
| 224 break; | |
| 225 same = (*magic_entry == *content) || (*magic_entry == '.' && *content); | |
| 226 if (!*content || !magic_entry) | |
|
Tom Finegan
2011/01/11 18:51:11
!*magic_entry again, assuming I'm correct above an
fbarchard1
2011/01/11 19:20:11
Done.
| |
| 227 break; | |
| 228 ++magic_entry; | |
| 229 ++content; | |
| 230 --len; | |
| 231 } | |
| 232 return same; | |
| 233 } | |
| 234 | |
| 218 static bool MatchMagicNumber(const char* content, size_t size, | 235 static bool MatchMagicNumber(const char* content, size_t size, |
| 219 const MagicNumber* magic_entry, | 236 const MagicNumber* magic_entry, |
| 220 std::string* result) { | 237 std::string* result) { |
| 221 const size_t len = magic_entry->magic_len; | 238 const size_t len = magic_entry->magic_len; |
| 222 | 239 |
| 223 // Keep kBytesRequiredForMagic honest. | 240 // Keep kBytesRequiredForMagic honest. |
| 224 DCHECK_LE(len, kBytesRequiredForMagic); | 241 DCHECK_LE(len, kBytesRequiredForMagic); |
| 225 | 242 |
| 226 // To compare with magic strings, we need to compute strlen(content), but | 243 // To compare with magic strings, we need to compute strlen(content), but |
| 227 // content might not actually have a null terminator. In that case, we | 244 // content might not actually have a null terminator. In that case, we |
| 228 // pretend the length is content_size. | 245 // pretend the length is content_size. |
| 229 const char* end = | 246 const char* end = |
| 230 static_cast<const char*>(memchr(content, '\0', size)); | 247 static_cast<const char*>(memchr(content, '\0', size)); |
| 231 const size_t content_strlen = | 248 const size_t content_strlen = |
| 232 (end != NULL) ? static_cast<size_t>(end - content) : size; | 249 (end != NULL) ? static_cast<size_t>(end - content) : size; |
| 233 | 250 |
| 234 bool match = false; | 251 bool match = false; |
| 235 if (magic_entry->is_string) { | 252 if (magic_entry->is_string) { |
| 236 if (content_strlen >= len) { | 253 if (content_strlen >= len) { |
| 237 // String comparisons are case-insensitive | 254 // String comparisons are case-insensitive |
| 238 match = (base::strncasecmp(magic_entry->magic, content, len) == 0); | 255 match = (base::strncasecmp(magic_entry->magic, content, len) == 0); |
| 239 } | 256 } |
| 240 } else { | 257 } else { |
| 241 if (size >= len) | 258 if (size >= len) |
| 242 match = (memcmp(magic_entry->magic, content, len) == 0); | 259 match = MagicCmp(magic_entry->magic, content, len); |
|
Tom Finegan
2011/01/11 18:51:11
Not that I have any major issue with being more sp
fbarchard1
2011/01/11 19:20:11
Done. Added comments
| |
| 243 } | 260 } |
| 244 | 261 |
| 245 if (match) { | 262 if (match) { |
| 246 result->assign(magic_entry->mime_type); | 263 result->assign(magic_entry->mime_type); |
| 247 return true; | 264 return true; |
| 248 } | 265 } |
| 249 return false; | 266 return false; |
| 250 } | 267 } |
| 251 | 268 |
| 252 static bool CheckForMagicNumbers(const char* content, size_t size, | 269 static bool CheckForMagicNumbers(const char* content, size_t size, |
| 253 const MagicNumber* magic, size_t magic_len, | 270 const MagicNumber* magic, size_t magic_len, |
| 254 base::Histogram* counter, std::string* result) { | 271 base::Histogram* counter, |
| 272 std::string* result) { | |
| 255 for (size_t i = 0; i < magic_len; ++i) { | 273 for (size_t i = 0; i < magic_len; ++i) { |
| 256 if (MatchMagicNumber(content, size, &(magic[i]), result)) { | 274 if (MatchMagicNumber(content, size, &(magic[i]), result)) { |
| 257 if (counter) counter->Add(static_cast<int>(i)); | 275 if (counter) counter->Add(static_cast<int>(i)); |
| 258 return true; | 276 return true; |
| 259 } | 277 } |
| 260 } | 278 } |
| 261 return false; | 279 return false; |
| 262 } | 280 } |
| 263 | 281 |
| 264 // Truncates |size| to |max_size| and returns true if |size| is at least | 282 // Truncates |size| to |max_size| and returns true if |size| is at least |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 // Now we look in our large table of magic numbers to see if we can find | 673 // Now we look in our large table of magic numbers to see if we can find |
| 656 // anything that matches the content. | 674 // anything that matches the content. |
| 657 if (SniffForMagicNumbers(content, content_size, | 675 if (SniffForMagicNumbers(content, content_size, |
| 658 &have_enough_content, result)) | 676 &have_enough_content, result)) |
| 659 return true; // We've matched a magic number. No more content needed. | 677 return true; // We've matched a magic number. No more content needed. |
| 660 | 678 |
| 661 return have_enough_content; | 679 return have_enough_content; |
| 662 } | 680 } |
| 663 | 681 |
| 664 } // namespace net | 682 } // namespace net |
| OLD | NEW |