1. 简介
HTTP Content-Type
头字段用于指示 HTTP 响应的 MIME 类型。
但许多 HTTP 服务器提供的 Content-Type
头字段值与实际响应内容并不匹配。
过去,Web 浏览器为兼容这些服务器,除了检查 Content-Type
头字段之外,还会检查 HTTP 响应内容,以确定实际的 MIME 类型。
没有明确规范如何 “嗅探(sniff)” MIME 类型,每个用户代理都被迫逆向工程其他用户代理的算法,以保持互操作性。 这种努力最终并不完全成功,导致了用户代理间行为的差异。 在某些情况下,这些差异带来了安全隐患,因为用户代理可能会将 HTTP 响应解释为与服务器预期不同的 MIME 类型。
当 “诚实” 服务器允许潜在恶意用户上传文件,并以低权限 MIME 类型提供这些文件内容时,安全问题最为严重。
例如,如果服务器认为客户端会将用户上传的文件视为图片(因此是良性的),但用户代理却将其视为 HTML(进而可能执行其中的脚本),攻击者就有可能窃取用户凭据并实施其他跨站脚本攻击。
(恶意服务器当然可以在 Content-Type
头字段中指定任意 MIME 类型。)
本文档描述了一种内容嗅探算法,在满足用户代理兼容性需求和现有 Web 内容的安全约束之间做出了平衡。 该算法起源于 Adam Barth、Juan Caballero 和 Dawn Song 的研究,基于主流用户代理的内容嗅探算法、现有 Web 内容的大型数据库以及在大量用户中部署所收集的度量数据。[SECCONTSNIFF]
2. 一致性要求
本文档中的关键词 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、 "SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY" 和 "OPTIONAL",其含义应按 RFC 2119 所述理解。 为便于阅读,这些关键词通常不会全部大写。 [KEYWORDS]
作为算法一部分的命令式要求(如 "去除所有前导空格字符" 或 "返回 false 并终止这些步骤"),应结合引入算法时使用的关键词来理解其含义。
以算法或具体步骤表述的一致性要求可以通过任何方式实现,只要最终结果等价即可。 特别需要注意的是,本规范定义的算法旨在易于理解,并不以高性能为目标。
3. 术语
本规范依赖 Infra 标准。[INFRA]
一个 HTTP 令牌码点(HTTP token code point) 是 U+0021 (!)、U+0023 (#)、U+0024 ($)、U+0025 (%)、 U+0026 (&)、U+0027 (')、U+002A (*)、U+002B (+)、U+002D (-)、U+002E (.)、U+005E (^)、U+005F (_)、 U+0060 (`)、U+007C (|)、U+007E (~),或一个 ASCII 字母或数字。
这与 token 产生式的值空间一致。 [HTTP-SEMANTICS]
一个 HTTP 引号字符串令牌码点(quoted-string token code point) 是 U+0009 TAB、范围 U+0020 SPACE 到 U+007E (~)(含)、或范围 U+0080 到 U+00FF (ÿ)(含)的码点。
这与 quoted-string 产生式的有效值空间一致。定义上它是 HTTP 令牌码点 的超集。[HTTP-SEMANTICS]
一个 二进制数据字节(binary data byte) 是 字节值在 0x00 到 0x08 (NUL 到 BS) 范围内,或 字节值为 0x0B (VT),或字节值在 0x0E 到 0x1A (SO 到 SUB) 范围内,或字节值在 0x1C 到 0x1F (FS 到 US) 范围内。
一个 空白字节(whitespace byte) (缩写为 0xWS)为下列任一 字节:0x09 (HT)、 0x0A (LF)、0x0C (FF)、0x0D (CR)、0x20 (SP)。
一个 标签终止字节(tag-terminating
byte)
(缩写为 0xTT)为下列任一 字节:0x20 (SP)、0x3E
(">
")。
本文中的数学运算符采用 [ENCODING] 中定义的符号。此外,按位非用 ~ 表示。
4. MIME 类型
4.1. MIME 类型表示
MIME 类型 表示 互联网媒体类型,定义见 Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types。也可称为 MIME 类型记录。[MIMETYPE]
标准建议始终使用 MIME 类型 这个术语,以避免与 Media Queries 中的 媒体类型 混淆。[MEDIAQUERIES]
MIME 类型的 主类型(type) 是非空 ASCII 字符串。
MIME 类型的 子类型(subtype) 是非空 ASCII 字符串。
MIME 类型的 参数(parameters) 是一个 有序映射(ordered map),其 键为 ASCII 字符串,值为仅包含 HTTP 引号字符串令牌码点的字符串。初始为空。
4.2. MIME 类型杂项
MIME 类型 mimeType 的 本质(essence) 是 mimeType 的 type,加上 U+002F (/) 和 subtype。
MIME 类型 被用户代理支持,指用户代理能够解析该 MIME 类型 的资源并将其展示给用户。
理想情况应更精确。参见 w3c/preload #113。
要最简化受支持的 MIME 类型,给定 MIME 类型 mimeType,执行如下步骤,返回 ASCII 字符串:
-
如果 mimeType 是 JavaScript MIME 类型,则返回 "
text/javascript
"。 -
如果 mimeType 是 JSON MIME 类型,则返回 "
application/json
"。 -
如果 mimeType 的 本质为 "
image/svg+xml
",则返回 "image/svg+xml
"。SVG 区别于其他 XML MIME 类型。
-
如果 mimeType 是 XML MIME 类型,则返回 "
application/xml
"。 -
返回空字符串。
本算法目的是让调用者区分具有不同处理模型的 MIME 类型(如 GIF 和 PNG),但除此之外尽量少暴露信息。
4.3. MIME 类型写入
有效 MIME 类型字符串 指符合 media-type 产生式的字符串。特别地,有效 MIME 类型字符串可包含 参数。[HTTP-SEMANTICS]
有效 MIME 类型字符串主要供一致性检查器使用。
"text/html
" 是 有效 MIME 类型字符串。
"text/html;
" 不是 有效 MIME 类型字符串,但 解析 MIME 类型仍会返回一个与输入为 "text/html
" 时相同的MIME 类型记录。
无参数有效 MIME 类型字符串是 不包含 U+003B (;) 的 有效 MIME 类型字符串。
4.4. 解析 MIME 类型
要解析 MIME 类型,给定字符串 input,执行如下步骤:
-
去除 input 的前后 HTTP 空白字符。
-
令 position 为 input 的 位置变量,初始指向 input 开头。
-
令 type 为 收集一串不是 U+002F (/) 的码点所得结果,输入为 input 和 position。
-
如果 type 为空字符串或不只包含 HTTP 令牌码点,则返回失败。
-
如果 position 已超出 input 末尾,则返回失败。
-
将 position 前进 1。(跳过 U+002F (/)。)
-
令 subtype 为 收集一串不是 U+003B (;) 的码点所得结果,输入为 input 和 position。
-
去除 subtype 尾部的 HTTP 空白字符。
-
如果 subtype 为空字符串或不只包含 HTTP 令牌码点,则返回失败。
-
令 mimeType 为新建的 MIME 类型记录,其 type 为 type(转为 ASCII 小写), subtype 为 subtype(转为 ASCII 小写)。
-
当 position 未超出 input 末尾时:
-
将 position 前进 1。(跳过 U+003B (;)。)
-
收集一段码点序列 ,这些码点是HTTP 空白符,从 input 的 position 开始。
效果类似 跳过 ASCII 空白,但用 HTTP 空白字符 而不是 ASCII 空白。
-
令 parameterName 为 收集一串不是 U+003B (;) 或 U+003D (=) 的码点所得结果,输入为 input 和 position。
-
将 parameterName 转为 ASCII 小写。
-
如果 position 未超出 input 末尾,则:
-
如果 position 已超出 input 末尾,则 中断。
-
令 parameterValue 为 null。
-
如果 input 的 position 处 码点为 U+0022 ("),则:
-
将 parameterValue 设为 收集 HTTP 引号字符串(输入:input、position、true)结果。
-
收集一串不是 U+003B (;) 的码点(输入:input、position)。
输入
text/html;charset="shift_jis"iso-2022-jp
,结果为text/html;charset=shift_jis
。
-
-
否则:
-
将 parameterValue 设为 收集一串不是 U+003B (;) 的码点所得结果(输入:input、position)。
-
去除 parameterValue 尾部 HTTP 空白字符。
-
如果 parameterValue 为空字符串,则 继续。
-
-
若全部满足:
- parameterName 非空
- parameterName 只包含 HTTP 令牌码点
- parameterValue 只包含 HTTP 引号字符串令牌码点
- 参数[parameterName] 不存在
-
-
返回 mimeType。
要从字节解析 MIME 类型,给定 字节序列 input,执行如下步骤:
-
令 string 为 input 同构解码后的结果。
-
返回 解析 MIME 类型(string)的结果。
4.5. 序列化 MIME 类型
要序列化 MIME 类型,给定 MIME 类型 mimeType,执行如下步骤:
-
令 serialization 为 mimeType 的 主类型、U+002F (/) 以及 mimeType 的 子类型 的拼接结果。
-
对于 mimeType 的每个 参数 name → value:
-
在 serialization 后添加 U+003B (;)。
-
在 serialization 后添加 name。
-
在 serialization 后添加 U+003D (=)。
-
如果 value 不仅包含 HTTP 令牌码点,或 value 为空字符串,则:
-
在 value 中每个 U+0022 (") 或 U+005C (\) 前加 U+005C (\)。
-
在 value 前添加 U+0022 (")。
-
在 value 后添加 U+0022 (")。
-
-
将 value 添加到 serialization。
-
-
返回 serialization。
要将 MIME 类型序列化为字节,给定 MIME 类型 mimeType,执行如下步骤:
-
令 stringSerialization 为 序列化 MIME 类型(mimeType)的结果。
-
返回 stringSerialization 同构编码后的结果。
4.6. MIME 类型分组
图像 MIME 类型(image MIME
type)指 MIME 类型 其 主类型为 "image
"。
音频或视频 MIME 类型(audio or
video MIME type)指 MIME
类型其主类型为 "audio
" 或
"video
",或 本质为 "application/ogg
"。
字体 MIME 类型(font MIME
type)指 MIME 类型其主类型为 "font
",或 本质为下列之一:[RFC8081]
application/font-cff
application/font-off
application/font-sfnt
application/font-ttf
application/font-woff
application/vnd.ms-fontobject
application/vnd.ms-opentype
基于 ZIP 的 MIME 类型(ZIP-based
MIME type)指 MIME 类型其子类型以 "+zip
" 结尾,或 本质为下列之一:
application/zip
归档 MIME 类型(archive MIME type)指 MIME 类型其本质为下列之一:
application/x-rar-compressed
application/zip
application/x-gzip
XML MIME 类型指 MIME 类型其子类型以 "+xml
" 结尾,或 本质为 "text/xml
" 或
"application/xml
"。[RFC7303]
HTML MIME 类型指 MIME 类型其本质为 "text/html
"。
可脚本 MIME 类型(scriptable
MIME type)指 XML MIME
类型、HTML MIME 类型,或 MIME 类型其本质为 "application/pdf
"。
JavaScript MIME 类型指 MIME 类型其本质为下列之一:
application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/javascript1.0
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/javascript1.4
text/javascript1.5
text/jscript
text/livescript
text/x-ecmascript
text/x-javascript
字符串为JavaScript MIME 类型本质匹配(essence match),如果它与某个 ASCII 不区分大小写的 JavaScript MIME 类型本质字符串一致。
此钩子用于
type
属性和
script
元素。[HTML]
JSON MIME 类型指 MIME 类型其子类型以 "+json
" 结尾,或 本质为 "application/json
" 或
"text/json
"。
5. 资源处理
资源是……
对于每个要处理的资源,用户代理必须跟踪以下相关元数据:
- 提供的 MIME 类型,由提供的 MIME 类型检测算法判定的MIME 类型。
- 检查 Apache bug 标志,默认未设置。
-
no-sniff
标志,如果用户代理不希望对该资源进行嗅探,则默认设置,否则为未设置。
用户代理可以使用外部信息(如之前对某站点的经验)来判断是否对特定资源关闭嗅探。用户代理还可以选择对所有资源关闭嗅探。但关闭嗅探并不意味着可以不使用MIME 类型嗅探算法。
- 计算出的 MIME 类型,由MIME 类型嗅探算法判定的MIME 类型。
5.1. 资源元数据解释
资源的提供的 MIME 类型由与该资源相关的外部来源提供。获取该信息的方法取决于资源的获取方式。
为了确定资源的提供的 MIME 类型,用户代理必须使用以下提供的 MIME 类型检测算法:
- 令 supplied-type 为 null。
- 如果资源是通过 HTTP 获取的,执行以下步骤:
- 如果该资源有一个或多个
Content-Type
头,执行以下步骤:- 将 supplied-type 设为与该资源关联的最后一个
Content-Type
头的值。通过 HTTP 获取的资源,其提供的 MIME 类型不依赖于文件扩展名,因为扩展名不可靠且容易伪造。
- 如果 supplied-type 完全等于下表中的某个值,则设置检查 Apache
bug 标志:
十六进制字节 ASCII 字节 74 65 78 74 2F 70 6C 61 69 6E text/plain
74 65 78 74 2F 70 6C 61 69 6E
3B 20 63 68 61 72 73 65 74 3D
49 53 4F 2D 38 38 35 39 2D 31text/plain; charset=ISO-8859-1
74 65 78 74 2F 70 6C 61 69 6E
3B 20 63 68 61 72 73 65 74 3D
69 73 6F 2D 38 38 35 39 2D 31text/plain; charset=iso-8859-1
74 65 78 74 2F 70 6C 61 69 6E
3B 20 63 68 61 72 73 65 74 3D
55 54 46 2D 38text/plain; charset=UTF-8
提供的 MIME 类型检测算法检测这些精确的字节序列,是因为一些较老版本的 Apache 存在一个 bug,导致其在提供未知MIME 类型文件时返回这些 Content-Type 头。
- 将 supplied-type 设为与该资源关联的最后一个
- 如果该资源有一个或多个
- 如果资源是直接从文件系统获取的,令 supplied-type 为文件系统提供的MIME 类型。
- 如果资源是通过其他协议(如 FTP)获取的,令 supplied-type 为该协议判定的MIME 类型(若有)。
- 如果 supplied-type 不是MIME
类型,则提供的 MIME
类型未定义。
终止这些步骤。
- 提供的 MIME 类型为 supplied-type。
5.2. 读取资源头部
要读取资源头部,执行如下步骤:
- 令 buffer 为一个字节序列。
- 从资源中读取字节到 buffer,直到满足下列任一条件:
如果 buffer 的字节数大于等于 1445,则MIME 类型嗅探算法在绝大多数情况下是确定性的。
但某些因素(如网络慢)可能导致用户代理无法在合理时间内读取到 1445 字节。
- 资源头部为 buffer。
6. 匹配 MIME 类型模式
字节模式(byte pattern)是用于模式匹配算法比对的字节序列。
模式掩码(pattern mask)是用于确定与字节模式比对时哪些字节有意义的字节序列,用于模式匹配算法。
在模式掩码中,0xFF 表示该字节严格有意义,0xDF 表示该字节以 ASCII 不区分大小写方式有意义,0x00 表示该字节无意义。
要判断一个字节序列是否匹配特定的字节模式,请使用如下模式匹配算法。该算法接收一个字节序列 input、一个字节模式 pattern、一个模式掩码 mask,以及一个要忽略的字节集合 ignored,返回 true 或 false。
-
令 s = 0。
-
当 s < input 的长度:
-
令 p = 0。
-
当 p < pattern 的长度:
-
令 maskedData 为 input[s] 和 mask[p] 进行按位与的结果。
-
如果 maskedData 不等于 pattern[p],返回 false。
-
令 s = s + 1。
-
令 p = p + 1。
-
-
返回 true。
6.1. 匹配图像类型模式
要确定字节模式 图像 MIME 类型的哪一项与 字节序列 input 匹配(如有),请使用如下图像类型模式匹配算法:
-
对下表每一行 row 执行如下步骤:
-
令 patternMatched 为 模式匹配算法(参数:input、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,则返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 图像 MIME 类型 说明 00 00 01 00 FF FF FF FF 无 image/x-icon
Windows Icon 签名。 00 00 02 00 FF FF FF FF 无 image/x-icon
Windows Cursor 签名。 42 4D FF FF 无 image/bmp
字符串 " BM
",BMP 签名。47 49 46 38 37 61 FF FF FF FF FF FF 无 image/gif
字符串 " GIF87a
",GIF 签名。47 49 46 38 39 61 FF FF FF FF FF FF 无 image/gif
字符串 " GIF89a
",GIF 签名。52 49 46 46 00 00 00 00 57 45 42 50 56 50 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF 无 image/webp
字符串 " RIFF
" 后四个字节,再加 "WEBPVP
"。89 50 4E 47 0D 0A 1A 0A FF FF FF FF FF FF FF FF 无 image/png
一个校验字节后跟 " PNG
",再跟 CR LF SUB LF,为 PNG 签名。FF D8 FF FF FF FF 无 image/jpeg
JPEG 起始标记及另一个标记的指示字节。 -
-
返回 undefined。
6.2. 匹配音频或视频类型模式
要确定字节模式 音频或视频 MIME 类型的哪一项与 字节序列 input 匹配(如有),请使用如下音频或视频类型模式匹配算法:
-
对下表每一行 row 执行如下步骤:
-
令 patternMatched 为 模式匹配算法(参数:input、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,则返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 音频或视频 MIME 类型 说明 46 4F 52 4D 00 00 00 00 41 49 46 46 FF FF FF FF 00 00 00 00 FF FF FF FF 无 audio/aiff
字符串 " FORM
" 后四个字节,再加 "AIFF
",即 AIFF 签名。49 44 33 FF FF FF 无 audio/mpeg
字符串 " ID3
",ID3v2 标记的 MP3 签名。4F 67 67 53 00 FF FF FF FF FF 无 application/ogg
字符串 " OggS
" 后跟 NUL,即 Ogg 容器签名。4D 54 68 64 00 00 00 06 FF FF FF FF FF FF FF FF 无 audio/midi
字符串 " MThd
" 后跟四个表示数字 6(32 位大端)的字节,即 MIDI 签名。52 49 46 46 00 00 00 00 41 56 49 20 FF FF FF FF 00 00 00 00 FF FF FF FF 无 video/avi
字符串 " RIFF
" 后四个字节,再加 "AVI
",即 AVI 签名。52 49 46 46 00 00 00 00 57 41 56 45 FF FF FF FF 00 00 00 00 FF FF FF FF 无 audio/wave
字符串 " RIFF
" 后四个字节,再加 "WAVE
",即 WAVE 签名。 -
-
如果 input 匹配 MP4 签名,返回 "
video/mp4
"。 -
如果 input 匹配 WebM 签名,返回 "
video/webm
"。 -
如果 input 匹配无 ID3 的 MP3 签名,返回 "
audio/mpeg
"。 -
返回 undefined。
6.2.1. MP4 签名
要判断一个字节序列是否匹配 MP4 签名,使用以下步骤:
- 令 sequence 为要匹配的字节序列,sequence[s] 表示第 s 个字节,sequence[0] 为第一个字节。
- 令 length 为 sequence 的字节数。
- 如果 length 小于 12,返回 false。
- 令 box-size 为 sequence[0] 到 sequence[3] 四个字节,按大端解释为 32 位无符号整数。
- 如果 length 小于 box-size 或 box-size 模 4 不为 0,返回 false。
- 如果 sequence[4] 到 sequence[7] 四个字节不等于 0x66 0x74 0x79 0x70(
ftyp
),返回 false。 - 如果 sequence[8] 到 sequence[10] 三个字节等于 0x6D 0x70 0x34(
mp4
),返回 true。 -
令 bytes-read 为 16。
这忽略了 “major brand” 版本号对应的四个字节。
-
当 bytes-read 小于 box-size 时,循环执行:
- 如果 sequence[bytes-read] 到 sequence[bytes-read + 2]
三个字节为 0x6D 0x70 0x34(
mp4
),返回 true。 - bytes-read 增加 4。
- 如果 sequence[bytes-read] 到 sequence[bytes-read + 2]
三个字节为 0x6D 0x70 0x34(
- 返回 false。
6.2.2. WebM 签名
要判断一个字节序列是否匹配 WebM 签名,使用以下步骤:
- 令 sequence 为要匹配的字节序列,sequence[s] 表示第 s 个字节,sequence[0] 为第一个字节。
- 令 length 为 sequence 的字节数。
- 如果 length 小于 4,返回 false。
- 如果 sequence[0] 到 sequence[3] 四个字节不等于 0x1A 0x45 0xDF 0xA3,返回 false。
- 令 iter 为 4。
-
当 iter 小于 length 且 iter 小于 38 时,循环执行:
- 如果 sequence[iter] 和 sequence[iter+1] 两个字节等于 0x42 0x82,
- iter 增加 1。
- 返回 false。
要解析 vint
,在 字节序列 sequence、长度 length、起始索引 iter
上,执行:
- 令 mask = 128。
- 令 max vint length = 8。
- 令 number size = 1。
- 令 index = 0。
-
当 number size 小于 max vint length 且小于 length 时,循环:
- 如果 sequence[index] & mask 不为零,终止循环。
- mask 右移一位。
- number size 增加 1。
- 令 parsed number = sequence[index] & ~mask。
- index 增加 1。
- 令 bytes remaining = number size - 1。
-
当 bytes remaining 不为零时,循环:
- parsed number 左移 8。
- parsed number |= sequence[index]。
- index 增加 1。
- 如果 index 大于等于 length,终止循环。
- bytes remaining 减 1。
- 返回 parsed number 和 number size
匹配填充序列 pattern 在序列 sequence 偏移 offset 到 end,当且仅当 sequence 长度大于 end,且区间 [offset, end] 的字节与 pattern 完全一致(前面可有若干 0x00),否则返回 false。
6.2.3. 无 ID3 的 MP3 签名
要判断一个字节序列是否匹配无 ID3 的 MP3 签名,使用以下步骤:
- 令 sequence 为要匹配的字节序列,sequence[s] 表示第 s 个字节,sequence[0] 为第一个字节。
- 令 length 为 sequence 的字节数。
- 初始化 s 为 0。
- 如果 匹配 mp3 头 返回 false,返回 false。
- 在 sequence 的 s 偏移上解析 mp3 帧。
- 令 skipped-bytes 为 计算 mp3 帧大小的返回值。
- 如果 skipped-bytes 小于 4,或 skipped-bytes 大于 s - length,返回 false。
- s 增加 skipped-bytes。
- 如果 匹配 mp3 头 返回 false,则返回 false,否则返回 true。
要匹配 mp3 头,使用长度为 length 的字节序列 sequence 在偏移 s 上:
- 若 length 小于 4,返回 false。
- 若 sequence[s] 不等于 0xff 且 sequence[s + 1] & 0xe0 不等于 0xe0,返回 false。
- 令 layer = (sequence[s+1] & 0x06) >> 1。
- 若 layer 为 0,返回 false。
- 令 bit-rate = (sequence[s+2] & 0xf0) >> 4。
- 若 bit-rate 为 15,返回 false。
- 令 sample-rate = (sequence[s+2] & 0x0c) >> 2。
- 若 sample-rate 为 3,返回 false。
- 令 freq 为 sample-rate 在 sample-rate 表中的值。
- 令 final-layer = 4 - (sequence[s+1])。
- 若 (final-layer & 0x06) >> 1 不为 3,返回 false。
- 返回 true。
要计算 mp3 帧大小,执行如下:
- 若 version 为 1,则 scale = 72,否则 scale = 144。
- 令 size = bitrate * scale / freq。
- 若 pad 不为零,则 size 增加 1。
- 返回 size。
要解析 mp3 帧,执行如下:
- version = (sequence[s + 1] & 0x18) >> 3。
- bitrate-index = (sequence[s + 2] & 0xf0) >> 4。
- 若 version & 0x01 非零,则 bitrate 取 mp2.5-rates 表中 bitrate-index 的值。
- 若 version & 0x01 为零,则 bitrate 取 mp3-rates 表中 bitrate-index 的值。
- samplerate-index = (sequence[s + 2] & 0x0c) >> 2。
- samplerate 为 sample-rate 表中 samplerate-index 的值。
- pad = (sequence[s + 2] & 0x02) >> 1。
索引 | mp3-rates |
---|---|
0 | 0 |
1 | 32000 |
2 | 40000 |
3 | 48000 |
4 | 56000 |
5 | 64000 |
6 | 80000 |
7 | 96000 |
8 | 112000 |
9 | 128000 |
10 | 160000 |
11 | 192000 |
12 | 224000 |
13 | 256000 |
14 | 320000 |
索引 | mp2.5-rates |
---|---|
0 | 0 |
1 | 8000 |
2 | 16000 |
3 | 24000 |
4 | 32000 |
5 | 40000 |
6 | 48000 |
7 | 56000 |
8 | 64000 |
9 | 80000 |
10 | 96000 |
11 | 112000 |
12 | 128000 |
13 | 144000 |
14 | 160000 |
索引 | 采样率 |
---|---|
0 | 44100 |
1 | 48000 |
2 | 32000 |
6.3. 匹配字体类型模式
要确定字体 MIME 类型的哪一个字节模式与 字节序列 input 匹配(如有),请使用如下字体类型模式匹配算法:
-
对下表每一行 row 执行如下步骤:
-
令 patternMatched 为 模式匹配算法(参数:input、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,则返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 字体 MIME 类型 说明 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 无 application/vnd.ms-fontobject
34 个字节后跟字符串 " LP
",即 Embedded OpenType 签名。00 01 00 00 FF FF FF FF 无 font/ttf
4 个字节表示版本号 1.0,TrueType 签名。 4F 54 54 4F FF FF FF FF 无 font/otf
字符串 " OTTO
",OpenType 签名。74 74 63 66 FF FF FF FF 无 font/collection
字符串 " ttcf
",TrueType Collection 签名。77 4F 46 46 FF FF FF FF 无 font/woff
字符串 " wOFF
",Web Open Font Format 1.0 签名。77 4F 46 32 FF FF FF FF 无 font/woff2
字符串 " wOF2
",Web Open Font Format 2.0 签名。 -
-
返回 undefined。
6.4. 匹配归档类型模式
要确定归档 MIME 类型的哪一个字节模式与 字节序列 input 匹配(如有),请使用如下归档类型模式匹配算法:
-
对下表每一行 row 执行如下步骤:
-
令 patternMatched 为 模式匹配算法(参数:input、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,则返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 归档 MIME 类型 说明 1F 8B 08 FF FF FF 无 application/x-gzip
GZIP 归档签名。 50 4B 03 04 FF FF FF FF 无 application/zip
字符串 " PK
" 后跟 ETX EOT,为 ZIP 归档签名。52 61 72 20 1A 07 00 FF FF FF FF FF FF FF 无 application/x-rar-compressed
字符串 " Rar
" 后跟 SUB BEL NUL,为 RAR 归档签名。 -
-
返回 undefined。
7. 确定资源的计算 MIME 类型
要确定资源的计算出的 MIME 类型,用户代理必须使用如下MIME 类型嗅探算法:
-
如果提供的 MIME 类型是XML MIME 类型或HTML MIME 类型,则计算出的 MIME 类型为提供的 MIME 类型。
终止这些步骤。
- 如果提供的 MIME
类型未定义,或其本质为
"
unknown/unknown
"、"application/unknown
" 或 "*/*
",则以 sniff-scriptable 标志为 no-sniff 标志的相反值,执行未知 MIME 类型识别规则,并终止这些步骤。 -
如果no-sniff 标志已设置,则计算出的 MIME 类型为提供的 MIME 类型。
终止这些步骤。
- 如果检查 Apache bug 标志已设置,执行文本或二进制资源判断规则,并终止这些步骤。
- 如果提供的 MIME 类型是被用户代理支持的图像 MIME 类型,则令 matched-type 为使用图像类型模式匹配算法,以资源头部为待匹配字节序列的结果。
-
如果 matched-type 不为 undefined,计算出的 MIME 类型为 matched-type。
终止这些步骤。
- 如果提供的 MIME 类型是被用户代理支持的音频或视频 MIME 类型,则令 matched-type 为使用音频或视频类型模式匹配算法,以资源头部为待匹配字节序列的结果。
-
如果 matched-type 不为 undefined,计算出的 MIME 类型为 matched-type。
终止这些步骤。
- 计算出的 MIME 类型为提供的 MIME 类型。
7.1. 识别未知 MIME 类型的资源
sniff-scriptable 标志用于未知 MIME 类型识别规则,判断是否需要嗅探可脚本 MIME 类型。
如果调用未知 MIME 类型识别规则时未指定 sniff-scriptable 标志,则其默认未设置。
要确定未知MIME 类型的资源 resource 的计算出的 MIME 类型,执行如下未知 MIME 类型识别规则:
-
如果 sniff-scriptable 标志已设置,对下表每一行 row 执行:
-
令 patternMatched 为 模式匹配算法(参数:resource 的资源头部、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 计算出的 MIME 类型 说明 3C 21 44 4F 43 54 59 50 45 20 48 54 4D 4C TT FF FF DF DF DF DF DF DF DF FF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <!DOCTYPE HTML
" 后跟标签终止字节。3C 48 54 4D 4C TT FF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <HTML
" 后跟标签终止字节。3C 48 45 41 44 TT FF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <HEAD
" 后跟标签终止字节。3C 53 43 52 49 50 54 TT FF DF DF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <SCRIPT
" 后跟标签终止字节。3C 49 46 52 41 4D 45 TT FF DF DF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <IFRAME
" 后跟标签终止字节。3C 48 31 TT FF DF FF FF 空白字节 text/html
不区分大小写的字符串 " <H1
" 后跟标签终止字节。3C 44 49 56 TT FF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <DIV
" 后跟标签终止字节。3C 46 4F 4E 54 TT FF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <FONT
" 后跟标签终止字节。3C 54 41 42 4C 45 TT FF DF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <TABLE
" 后跟标签终止字节。3C 41 TT FF DF FF 空白字节 text/html
不区分大小写的字符串 " <A
" 后跟标签终止字节。3C 53 54 59 4C 45 TT FF DF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <STYLE
" 后跟标签终止字节。3C 54 49 54 4C 45 TT FF DF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <TITLE
" 后跟标签终止字节。3C 42 TT FF DF FF 空白字节 text/html
不区分大小写的字符串 " <B
" 后跟标签终止字节。3C 42 4F 44 59 TT FF DF DF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <BODY
" 后跟标签终止字节。3C 42 52 TT FF DF DF FF 空白字节 text/html
不区分大小写的字符串 " <BR
" 后跟标签终止字节。3C 50 TT FF DF FF 空白字节 text/html
不区分大小写的字符串 " <P
" 后跟标签终止字节。3C 21 2D 2D TT FF FF FF FF FF 空白字节 text/html
字符串 " <!--
" 后跟标签终止字节。3C 3F 78 6D 6C FF FF FF FF FF 空白字节 text/xml
字符串 " <?xml
"。25 50 44 46 2D FF FF FF FF FF 无 application/pdf
字符串 " %PDF-
",PDF 签名。 -
-
对下表每一行 row 执行:
-
令 patternMatched 为 模式匹配算法(参数:resource 的资源头部、行首列、行次列、行第三列)的结果。
-
如果 patternMatched 为 true,返回 row 的第四列值。
字节模式 模式掩码 要忽略的前导字节 计算出的 MIME 类型 说明 25 21 50 53 2D 41 64 6F 62 65 2D FF FF FF FF FF FF FF FF FF FF FF 无 application/postscript
字符串 " %!PS-Adobe-
",PostScript 签名。FE FF 00 00 FF FF 00 00 无 text/plain
UTF-16BE BOM FF FE 00 00 FF FF 00 00 无 text/plain
UTF-16LE BOM EF BB BF 00 FF FF FF 00 无 text/plain
UTF-8 BOM 用户代理可以隐式扩展此表以支持额外的MIME 类型。
但用户代理不应隐式扩展此表为任何已在表中的计算出的 MIME 类型增加新的字节模式,以避免权限提升漏洞。
用户代理在扩展该表时不得引入权限提升漏洞。
-
-
令 matchedType 为使用图像类型模式匹配算法,以 resource 的资源头部为参数的结果。
-
如果 matchedType 不为 undefined,返回 matchedType。
-
令 matchedType 为使用音频或视频类型模式匹配算法,以 resource 的资源头部为参数的结果。
-
如果 matchedType 不为 undefined,返回 matchedType。
-
令 matchedType 为使用归档类型模式匹配算法,以 resource 的资源头部为参数的结果。
-
如果 matchedType 不为 undefined,返回 matchedType。
-
返回 "
application/octet-stream
"。
7.2. 嗅探标签错误的二进制资源
要判断一个二进制资源是否被错误标记为纯文本,执行如下文本或二进制资源判断规则:
- 令 length 为资源头部中的字节数。
- 如果 length 大于等于 2 且前 2 个字节为 0xFE 0xFF(UTF-16BE BOM)或 0xFF 0xFE(UTF-16LE BOM),则计算出的 MIME 类型为
"
text/plain
"。终止这些步骤。
- 如果 length 大于等于 3 且前 3 个字节为 0xEF 0xBB 0xBF(UTF-8 BOM),则计算出的 MIME 类型为
"
text/plain
"。终止这些步骤。
- 如果资源头部不包含任何二进制数据字节,则计算出的 MIME 类型为
"
text/plain
"。终止这些步骤。
- 计算出的 MIME 类型为
"
application/octet-stream
"。必须确保文本或二进制资源判断规则永远不会将计算出的 MIME 类型判定为可脚本 MIME 类型,否则可能带来权限提升攻击。
8. 上下文相关嗅探
上下文是……
在某些上下文中,仅识别属于特定MIME 类型子集的资源才有意义。
在这种上下文中,适合使用上下文相关嗅探算法,代替MIME 类型嗅探算法,以确定计算出的 MIME 类型。
上下文相关嗅探算法仅在资源为某一特定上下文相关的MIME 类型时,确定该资源的计算出的 MIME 类型。
8.1. 浏览上下文中的嗅探
使用MIME 类型嗅探算法。
8.2. 图像上下文中的嗅探
要确定带有图像 MIME 类型的资源的计算出的 MIME 类型,执行如下专门针对图像嗅探的规则:
-
如果提供的 MIME
类型是XML MIME 类型,则计算出的 MIME
类型为提供的 MIME
类型。
终止这些步骤。
- 令 image-type-matched 为使用图像类型模式匹配算法,以资源头部为待匹配字节序列的结果。
-
如果 image-type-matched 不为 undefined,计算出的 MIME 类型为 image-type-matched。
终止这些步骤。
- 计算出的 MIME 类型为提供的 MIME 类型。
8.3. 音频或视频上下文中的嗅探
要确定具有音频或视频 MIME 类型的资源的计算出的 MIME 类型,执行如下专门针对音频和视频嗅探的规则:
-
如果提供的 MIME
类型是XML MIME 类型,则计算出的 MIME
类型为提供的 MIME
类型。
终止这些步骤。
- 令 audio-or-video-type-matched 为使用音频或视频类型模式匹配算法,以资源头部为待匹配字节序列的结果。
-
如果 audio-or-video-type-matched 不为 undefined,计算出的 MIME 类型为
audio-or-video-type-matched。
终止这些步骤。
- 计算出的 MIME 类型为提供的 MIME 类型。
8.4. 插件上下文中的嗅探
要确定在插件上下文中获取的资源的计算出的 MIME 类型,执行如下插件上下文嗅探规则:
- 如果提供的
MIME 类型未定义,计算出的 MIME 类型为 "
application/octet-stream
"。 - 计算出的 MIME 类型为提供的 MIME 类型。
8.5. 样式上下文中的嗅探
要确定在样式上下文中获取的资源的计算出的 MIME 类型,执行如下样式上下文嗅探规则:
- 如果提供的 MIME 类型未定义,……
- 计算出的 MIME 类型为提供的 MIME 类型。
8.6. 脚本上下文中的嗅探
要确定在脚本上下文中获取的资源的计算出的 MIME 类型,执行如下脚本上下文嗅探规则:
- 如果提供的 MIME 类型未定义,……
- 计算出的 MIME 类型为提供的 MIME 类型。
8.7. 字体上下文中的嗅探
要确定具有字体 MIME 类型的资源的计算出的 MIME 类型,执行如下专门针对字体嗅探的规则:
-
如果提供的 MIME
类型是XML MIME 类型,则计算出的 MIME
类型为提供的 MIME
类型。
终止这些步骤。
- 令 font-type-matched 为使用字体类型模式匹配算法,以资源头部为待匹配字节序列的结果。
-
如果 font-type-matched 不为 undefined,计算出的 MIME 类型为 font-type-matched。
终止这些步骤。
- 计算出的 MIME 类型为提供的 MIME 类型。
8.8. 文本轨道上下文中的嗅探
计算出的 MIME
类型为 "text/vtt
"。
8.9. 缓存清单上下文中的嗅探
计算出的 MIME
类型为 "text/cache-manifest
"。
致谢
特别感谢 Adam Barth 和 Ian Hickson 维护了本规范的早期版本。
还要感谢 Alfred Hönes、 Andreu Botella、 Anne van Kesteren、 Ben Eidson、 Boris Zbarsky、 Darien Maillet Valentine、 David Singer、 Domenic Denicola、 Henri Sivonen、 Jean-Yves Avenard、 Jonathan Neal、 Joshua Cranmer、 Larry Masinter、 罗泽轩、 Mariko Kosaka、 Mark Pilgrim、 Paul Adenot、 Peter Occil、 Rob Buis、 Russ Cox、 Simon Pieters 以及 triple-underscore ,感谢他们的重要贡献。
本标准由 Gordon P. Hemsley(me@gphemsley.org)撰写。
知识产权声明
Copyright © WHATWG(Apple、Google、Mozilla、Microsoft)。本作品采用 知识共享署名 4.0 国际许可证 许可。若本规范部分内容被整合进源代码,则该部分源代码按 BSD 3-Clause License 许可。
本规范是 Living Standard。如需专利审核版本,请参见 Living Standard Review Draft。