1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! mime-sniffer: Detecting mime types base on content sniffer.
//!
//! ***The detection workflow was copied from
//! [Chromium](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/mime_sniffer.cc)***
//!
//! Detecting mime types is a tricky business because we need to balance
//! compatibility concerns with security issues.  Here is a survey of how other
//! browsers behave and then a description of how we intend to behave.
//!
//! ### HTML payload, no Content-Type header:
//!
//! * IE 7: Render as HTML
//! * Firefox 2: Render as HTML
//! * Safari 3: Render as HTML
//! * Opera 9: Render as HTML
//!
//! Here the choice seems clear:
//!
//! => Chrome: Render as HTML
//!
//! ### HTML payload, Content-Type: "text/plain":
//!
//! * IE 7: Render as HTML
//! * Firefox 2: Render as text
//! * Safari 3: Render as text
//! (Note: Safari will Render as HTML if the URL has an HTML extension)
//! * Opera 9: Render as text
//!
//! Here we choose to follow the majority (and break some compatibility with IE).
//! Many folks dislike IE's behavior here.
//!
//! => Chrome: Render as text
//!
//! We generalize this as follows.  If the Content-Type header is text/plain
//! we won't detect dangerous mime types (those that can execute script).
//!
//! ### HTML payload, Content-Type: "application/octet-stream":
//!
//! * IE 7: Render as HTML
//! * Firefox 2: Download as application/octet-stream
//! * Safari 3: Render as HTML
//! * Opera 9: Render as HTML
//!
//! We follow Firefox.
//!
//! => Chrome: Download as application/octet-stream
//!
//! One factor in this decision is that IIS 4 and 5 will send
//! application/octet-stream for .xhtml files (because they don't recognize
//! the extension).  We did some experiments and it looks like this doesn't occur
//! very often on the web.  We choose the more secure option.
//!
//! ### GIF payload, no Content-Type header:
//!
//! * IE 7: Render as GIF
//! * Firefox 2: Render as GIF
//! * Safari 3: Download as Unknown
//! (Note: Safari will Render as GIF if the URL has an GIF extension)
//! * Opera 9: Render as GIF
//!
//! The choice is clear.
//!
//! => Chrome: Render as GIF
//!
//! Once we decide to render HTML without a Content-Type header, there isn't much
//! reason not to render GIFs.
//!
//! ### GIF payload, Content-Type: "text/plain":
//!
//! * IE 7: Render as GIF
//! * Firefox 2: Download as application/octet-stream (Note: Firefox will
//!                              Download as GIF if the URL has an GIF extension)
//! * Safari 3: Download as Unknown (Note: Safari will Render as GIF if the
//!                                        URL has an GIF extension)
//! * Opera 9: Render as GIF
//!
//! Displaying as text/plain makes little sense as the content will look like
//! gibberish.  Here, we could change our minds and download.
//!
//! => Chrome: Render as GIF
//!
//! ### GIF payload, Content-Type: "application/octet-stream":
//!
//! * IE 7: Render as GIF
//! * Firefox 2: Download as application/octet-stream (Note: Firefox will
//!                              Download as GIF if the URL has an GIF extension)
//! * Safari 3: Download as Unknown (Note: Safari will Render as GIF if the
//!                                        URL has an GIF extension)
//! * Opera 9: Render as GIF
//!
//! We used to render as GIF here, but the problem is that some sites want to
//! trigger downloads by sending application/octet-stream (even though they
//! should be sending Content-Disposition: attachment).  Although it is safe
//! to render as GIF from a security perspective, we actually get better
//! compatibility if we don't sniff from application/octet stream at all.
//!
//! => Chrome: Download as application/octet-stream
//!
//! ### XHTML payload, Content-Type: "text/xml":
//!
//! * IE 7: Render as XML
//! * Firefox 2: Render as HTML
//! * Safari 3: Render as HTML
//! * Opera 9: Render as HTML
//!
//! The layout tests rely on us rendering this as HTML.
//! But we're conservative in XHTML detection, as this runs afoul of the
//! "don't detect dangerous mime types" rule.
//!
//! Note that our definition of HTML payload is much stricter than IE's
//! definition and roughly the same as Firefox's definition.
//!
//! # Examples
//!
//! ```rust
//! use mime_sniffer::MimeTypeSniffer;
//!
//! assert_eq!(Some("application/pdf"), b"%PDF-1.5".sniff_mime_type());
//! ```
//!
//! ```rust
//! #[macro_use]
//! extern crate mime;
//! extern crate mime_sniffer;
//!
//! use mime_sniffer::{HttpRequest, MimeTypeSniffer, MimeTypeSnifferExt};
//!
//! fn main() {
//!     let req = HttpRequest {
//!         content: b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1",
//!         url: &"http://localhost/notes.ppt",
//!         type_hint: "text/plain",
//!     };
//!
//!     assert_eq!(req.sniff_mime_type(), Some("application/vnd.ms-powerpoint"));
//!     assert_eq!(req.sniff_mime_type_ext().unwrap().type_(), mime::APPLICATION);
//! }
//! ```
extern crate mime;
extern crate url;

mod magic;
mod api;

pub use api::{HttpRequest, MimeTypeSniffable, MimeTypeSniffer, MimeTypeSnifferExt};