mime_sniffer/lib.rs
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
//! ## mime-sniffer: Detecting mime types base on content sniffer.
//!
//! ***The detection workflow was copied from
//! [Chromium](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/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
//!
//! 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 api;
mod magic;
pub use api::{HttpRequest, MimeTypeSniffable, MimeTypeSniffer, MimeTypeSnifferExt};