Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1410)

Unified Diff: net/base/mime_sniffer.cc

Issue 12703012: Have media gallery (through native media file util) use MIME sniffer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Oops, forgot, I can now add Flash Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/mime_sniffer.cc
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index d53b567ffec075a6f4b871ffafbe388f00fb2b63..68881f1d16c2c40a2a1e73bb026754892eff7187 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -116,9 +116,20 @@ struct MagicNumber {
bool is_string;
};
+struct MagicMaskNumber {
vandebo (ex-Chrome) 2013/04/29 19:43:50 I think it's ok to modify MagicNumber. It's an im
Kevin Bailey 2013/04/30 20:57:56 Done.
+ const char* mime_type;
+ const char* magic;
+ size_t magic_len;
+ bool is_string;
+ const char* mask; // must have same length as |magic|
+};
+
#define MAGIC_NUMBER(mime_type, magic) \
{ (mime_type), (magic), sizeof(magic)-1, false },
+#define MAGIC_MASK(mime_type, magic, mask) \
+ { (mime_type), (magic), sizeof(magic)-1, false, (mask) },
+
// Magic strings are case insensitive and must not include '\0' characters
#define MAGIC_STRING(mime_type, magic) \
{ (mime_type), (magic), sizeof(magic)-1, true },
@@ -176,6 +187,25 @@ static const MagicNumber kMagicNumbers[] = {
// On balance, we do not include these patterns.
};
+static const MagicMaskNumber kMagicMaskNumbers[] = {
vandebo (ex-Chrome) 2013/04/29 19:43:50 These aren't all mask'd magic numbers... maybe kEx
Kevin Bailey 2013/04/30 20:57:56 Done.
+ MAGIC_NUMBER("image/x-xbitmap", "#define")
+ MAGIC_NUMBER("image/x-icon", "\x00\x00\x01\x00")
+ MAGIC_NUMBER("image/svg+xml", "<?xml_version=")
+ MAGIC_NUMBER("audio/wav", "RIFF....WAVEfmt ")
+ MAGIC_NUMBER("video/avi", "RIFF....AVI LIST")
+ MAGIC_NUMBER("video/x-ms-wmv", "RIFF....AVI LIST")
+ MAGIC_NUMBER("audio/ogg", "OggS")
+ MAGIC_MASK("video/mpeg", "\x00\x00\x01\xB0", "\xFF\xFF\xFF\xF0")
+ MAGIC_MASK("audio/mpeg", "\xFF\xE0", "\xFF\xE0")
+ MAGIC_NUMBER("video/3gpp", "....ftyp3g")
+ MAGIC_NUMBER("video/3gpp", "....ftypavcl")
+ MAGIC_NUMBER("video/mp4", "....ftyp")
+ MAGIC_NUMBER("video/quicktime", "MOVI")
+ MAGIC_NUMBER("application/x-shockwave-flash", "CWS")
+ MAGIC_NUMBER("application/x-shockwave-flash", "FWS")
+ MAGIC_NUMBER("video/x-flv", "FLV")
+};
+
// Our HTML sniffer differs slightly from Mozilla. For example, Mozilla will
// decide that a document that begins "<!DOCTYPE SOAP-ENV:Envelope PUBLIC " is
// HTML, but we will not.
@@ -264,6 +294,61 @@ static bool MatchMagicNumber(const char* content, size_t size,
return false;
}
+// Like MagicCmp() except that it ANDs each byte with a mask before
+// the comparison, because there are some bits we don't care about.
+static bool MagicMaskCmp(const char* magic_entry, const char* mask,
+ const char* content, size_t len) {
+ while (len) {
+ if ((*magic_entry != '.') && (*magic_entry != (*mask & *content)))
+ return false;
+ ++magic_entry;
+ ++content;
+ ++mask;
+ --len;
+ }
+ return true;
+}
+
+static bool MatchMagicMaskNumber(const char* content, size_t size,
+ const MagicMaskNumber* magic_entry,
+ std::string* result) {
+ const size_t len = magic_entry->magic_len;
+
+ // Keep kBytesRequiredForMagic honest.
+ DCHECK_LE(len, kBytesRequiredForMagic);
+
+ // To compare with magic strings, we need to compute strlen(content), but
+ // content might not actually have a null terminator. In that case, we
+ // pretend the length is content_size.
+ const char* end =
+ static_cast<const char*>(memchr(content, '\0', size));
+ const size_t content_strlen =
+ (end != NULL) ? static_cast<size_t>(end - content) : size;
+
+ bool match = false;
+ if (magic_entry->is_string) {
+ if (content_strlen >= len) {
+ // String comparisons are case-insensitive
+ match = (base::strncasecmp(magic_entry->magic, content, len) == 0);
+ }
+ } else {
+ if (size >= len) {
+ if (magic_entry->mask) {
+ match = MagicMaskCmp(magic_entry->magic, magic_entry->mask, content,
+ len);
+ } else {
+ match = MagicCmp(magic_entry->magic, content, len);
+ }
+ }
+ }
+
+ if (match) {
+ result->assign(magic_entry->mime_type);
+ return true;
+ }
+ return false;
+}
+
static bool CheckForMagicNumbers(const char* content, size_t size,
const MagicNumber* magic, size_t magic_len,
base::HistogramBase* counter,
@@ -277,6 +362,30 @@ static bool CheckForMagicNumbers(const char* content, size_t size,
return false;
}
+static bool CheckForMagicMaskNumbers(const char* content, size_t size,
+ const MagicMaskNumber* magic,
+ size_t magic_len,
+ std::string* result) {
+ for (size_t i = 0; i < magic_len; ++i) {
+ if (MatchMagicMaskNumber(content, size, &(magic[i]), result))
+ return true;
+ }
+ return false;
+}
+
+bool IdentifyExtraMimeType(const char* content, size_t size,
+ std::string* result) {
+ // First check the extra table.
+ if (CheckForMagicMaskNumbers(content, size, kMagicMaskNumbers,
+ sizeof(kMagicMaskNumbers) /
+ sizeof(MagicMaskNumber), result))
+ return true;
+ // Finally check the original table.
+ return CheckForMagicNumbers(content, size, kMagicNumbers,
+ sizeof(kMagicNumbers) / sizeof(MagicNumber),
+ NULL, result);
+}
+
// Truncates |size| to |max_size| and returns true if |size| is at least
// |max_size|.
static bool TruncateSize(const size_t max_size, size_t* size) {

Powered by Google App Engine
This is Rietveld 408576698