[57] [DFN[zlib]] は、 [[DEFLATE]] を用いる[[圧縮形式]]です。

* 仕様書

[58] [[zlib]] は [DFN[RFC 1950]] により定義されています。

[REFS[
- [20] '''[CITE@en[RFC 1950 - ZLIB Compressed Data Format Specification version 3.3]] ([TIME[2017-09-17 17:15:13 +09:00]]) <https://tools.ietf.org/html/rfc1950>'''
- [2] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-4.2.2>
- [6] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-8.5>
- [7] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-06-07 01:55:45 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#page-12>
- [13] [CITE@en[RFC 3229 - Delta encoding in HTTP]] ([TIME[2014-10-26 21:15:25 +09:00]] 版) <http://tools.ietf.org/html/rfc3229#section-10.1>
- [15] [CITE@en[RFC 3229 - Delta encoding in HTTP]] ([TIME[2014-10-26 21:15:25 +09:00]] 版) <http://tools.ietf.org/html/rfc3229#section-10.9>
- [70] [CITE@en[RFC 6713 - The 'application/zlib' and 'application/gzip' Media Types]] ([TIME[2017-09-24 17:26:31 +09:00]]) <https://tools.ietf.org/html/rfc6713>
]REFS]

* 構文

[27] [DFN[zlib stream]] は、次のような[[バイト列]]です。

[FIG(list members)[

: [ABBR[[[CMF]]][Compression Method and flags]] 1バイト :
第0ビットから第3ビットが [[CM]]、
第4ビットから第7ビットが [[CINFO]] です。 [SRC[>>20]]
: [ABBR[[[FLG]]][FLaGs]] 1バイト :
第0ビットから第4ビットが [[FCHECK]]、
第5ビットが [[FDICT]]、
第6ビットと第7ビットが [[FLEVEL]] です。 [SRC[>>20]]
: [[DICTID]] :
[[preset dictionary]] の識別子を表します。
[[FLG]] の [[FDICT]] が設定されている場合のみ存在します。
: 圧縮データ :
圧縮された実際のデータです。
: [[ADLER32]] :
[[検査和]]です。

]FIG]

[35] 入力データの長さが不十分なときにどう処理するべきかは不明です。

[72] [[RFC 6713]] は [[zlib]] を識別する[[魔法数]]として、

- 最初のバイトは通常 [N[0x78]] だが、 [N[0x08]], [N[0x18]], [N[0x28]], [N[0x38]],
[N[0x48]], [N[0x58]], [N[0x68]] ともなり得る
- 最初の2バイトを[[大エンディアン]]の[[16ビット符号無し整数]]と解釈すると
[N[31]] の[[倍数]]である

... を挙げています [SRC[>>70]]。

** CM

[28] [DFN[CM]] (Compression method) は、
[RUBYB[圧縮方式]@en[compression method]]を表します。 [SRC[>>20]]

[29] [N[8]] は、 [[DEFLATE]] ([RUBYB[窓サイズ]@en[window size]]
32KB [[以下]]) を表します。 [SRC[>>20]]

[30] [N[15]] は、予約されています。
将来の版で、圧縮データ前に追加の欄が存在することを示すために使うかもしれません。 [SRC[>>20]]

[36] [N[8]] 以外の場合、展開器は、エラーとしなければなりません。 [SRC[>>20]]

** FCHECK

[38] [DFN[FCHECK]] は、
[[CMF]] と [[FLG]] の検査ビットであり、
[[CMF]] × [N[256]] × [[FLG]] が [N[31]] の[[倍数]]となるような値に設定しなければなりません。
[SRC[>>20]]

[39] [[展開器]]は [[FLG]] を検査しなければならない [SRC[>>20]] とされていますが、
不正なデータをどう処理するべきかは不明です。

** FDICT

[40] [DFN[FDICT]] は、
設定されている場合、 [[DICTID]] が [[FLG]] の直後に現れることを表します。
[SRC[>>20]]

[54] [[zlib]] を用いる[[データ形式]]が [[preset dictionary]] を用いない場合、
[[圧縮器]]は [[FDICT]] を設定してはなりません。[[展開器]]は拒絶しなければなりません。 [SRC[>>20]]

** FLEVEL

[44] [DFN[FLEVEL]] (圧縮レベル) は、圧縮方式依存です。 [SRC[>>20]]

[45] [[CM]] が [N[8]] の場合、次の通りの意味です。 [SRC[>>20]]

- [N[0]] - [[圧縮器]]は最速アルゴリズムを使った
- [N[1]] - [[圧縮器]]は速いアルゴリズムを使った
- [N[2]] - [[圧縮器]]は既定のアルゴリズムを使った
- [N[3]] - [[圧縮器]]は最大圧縮の最遅のアルゴリズムを使った

[46] この情報は[[展開]]には使いません。 [SRC[>>20]]

[47] この情報は再圧縮する意味があるかどうかの判断に使えます。 [SRC[>>20]]

;; [59] [[gzip]] には [[XFL]] があり似た意味で使われていますが、値は異なります。

** DICT (DICTID)

[41] [[FDICT]] ビットが設定されている場合、 [DFN[DICTID]] 
(辞書識別子 [SRC[>>20]]) を記述します。

[42] 辞書 ([DFN[preset dictionary]]) とは、
最初に[[圧縮器]]に与える[[バイト列]]で、圧縮データ自体ではないものです。 
[[DICTID]] は、この[[バイト列]]の [[Adler-32]] [[検査和]]です。 [SRC[>>20]]

[53] 他の[[データ形式]]が [[zlib]] を用いる時、
[[圧縮器]]はその[[データ形式]]が定めた [[preset dictionary]] を用いて構いません。
[[展開器]]はそのすべての [[preset dictionary]] に対応しなければなりません。 [SRC[>>20]]

[43] [[展開器]]は、この [[DICTID]] を使ってどの [[preset dictionary]]
が使われているかを判断できます。 [SRC[>>20]]

[55] [[展開器]]は、 [[FDICT]] が設定されていて [[DICTID]] が未知の [[preset dictionary]]
の場合、エラーとしなければなりません。 [SRC[>>20]]

** 圧縮データ

[48] [RUBYB[圧縮データ]@en[compressed data]] [SRC[>>20]] は、
[[圧縮]]された実際のデータです。

[49] [[CM]] が [N[8]] の時、
[[DEFLATE]] の圧縮データです。 [SRC[>>20]]

[50] 他の形式は未定義です。 [SRC[>>20]]

** ADLER32

[51] [DFN[ADLER32]] (Adler-32 [RUBYB[検査和]@en[checksum]]) は、
未圧縮データ (辞書データを含みません。)
について [[Adler-32]] [[検査和]]を計算したものです。 [SRC[>>20]]

[56] [[展開器]]は [[ADLER32]] を検査しなければならない [SRC[>>20]] とされていますが、
不適切な場合どう処理するべきかは不明です。

** 余分データ

[34] それ以後にデータがあったとしても、 [[zlib stream]] の一部ではありません。 [SRC[>>20]]


* 符号化 (圧縮)

[22] [[圧縮器]]は、
[[RFC 1950]] のすべての要件を満たすデータを生成しなければなりません。 [SRC[>>20]]

[52] [[preset dictionary]] に対応する義務はありません。 [SRC[>>20]]

* 復号 (展開)

[23] [[展開器]]は、[[RFC 1950]] に適合する任意のデータを受理し展開できなければなりません。
[SRC[>>20]]

* MIME 型

[71] [[MIME型]]として [DFN[[CODE(MIME)@en[application/zlib]]]] が
[[RFC 6713]] で定義されています [SRC[>>70]]。


* 文脈

[18] データ形式としての [[ZLIB]] は次の場面で用いられています。

[FIG(short list)[

- [[gzip]]
- [[HTTP]] [CODE(HTTP)@en[[[deflate]]]]
- [[PNG]]
- [[WOFF]]
]FIG]

[32] [[gzip]] として使われるものは、 [[gzip]] を参照。


* 内容符号化・転送符号化 [CODE[deflate]]

[3] [[内容符号化]]・[[転送符号化]] [DFN[[CODE(HTTP)@en[[[deflate]]]]]] は、
[[LZ77]] 圧縮法と[[ハフマン符号化]]の組み合わせを用いた [[RFC 1951]]
「[[deflate]]」圧縮データストリームを含んだ [[RFC 1950]]
「[[zlib]]」データ形式を表します [SRC[>>2, >>6, >>7]]。

[4] 実装によっては [[zlib]] を用いない [[DEFLATE]] 圧縮データを
[CODE(HTTP)@en[[[deflate]]]] として送りますが、これは[[不適合]] [SRC[>>2]] とされています。

;; [5] それをどう扱うべきかは規定されていません。

[61] [[zlib]] の[[ドキュメント]]は、
[[Microsoft]] などいくつかの[[サーバー]]と[[ブラウザー]]が誤って
[CODE[deflate]] を [[DEFLATE]] の意味で使っているため、
[CODE[gzip]] を使う方がおそらくより信頼性が高いだろうと指摘しています [SRC[>>60]]。

[REFS[
- [60] [CITE[Frequently Asked Questions about zlib]] ([TIME[2005-02-21 07:10:26 +09:00]]) <http://www.gzip.org/zlib/zlib_faq.html#faq38>
]REFS]

* 歴史

[24] 3.1 版が最初の公開版です。 [SRC[>>20]]

[25] 3.2 版で用語の変更と [[Adler-32]] コード例の改訂がありました。 [SRC[>>20]]

[26] 3.3 版で [[preset dictionary]] が導入され、 [[RFC]] 化されました。 [SRC[>>20]]

** 実現値操作 [CODE(HTTP)@en[deflate]]

[14] [[実現値操作]] [DFN[[CODE(HTTP)@en[[[deflate]]]]]] は、
[[内容符号化]] [CODE(HTTP)@en[[[deflate]]]] と同じです [SRC[>>13]]。

[16] [CODE(HTTP)@en[[[gdiff]]]] や [CODE(HTTP)@en[[[diffe]]]] は[[圧縮]]によって大きくサイズを削減できますから、
[CODE(HTTP)@en[[[deflate]]]] も実装することが[RUBYB[強く推奨]@en[strongly recommended]]されています [SRC[>>15]]。

[89] [[実現値操作]] [CODE[deflate]] は[[IANA登録簿]]には [[RFC 2616]] を出典として登録されています [SRC[>>88]]。
[[RFC 723x]] 出版後も出典は更新されていません。 [TIME[2014-11-19T16:22:24.500Z]]

[REFS[
- [88] [CITE[Instance Manipulation Values]] ([TIME[2014-01-31 02:45:13 +09:00]] 版) <http://www.iana.org/assignments/inst-man-values/inst-man-values.xhtml>
]REFS]

* メモ

[21] [[ランダムアクセス]]は設計上の想定外とされています [SRC[>>20]]。

[11] [CITE[zlib Home Site]]
( ([TIME[2014-03-27 06:36:36 +09:00]] 版))
<http://www.zlib.net/>

[12] [CITE@ja[zlib - Wikipedia]]
([TIME[2016-01-10 16:10:12 +09:00]] 版)
<https://ja.wikipedia.org/wiki/Zlib>

[1] [CITE[java - Handling HTTP ContentEncoding "deflate" - Stack Overflow]]
([TIME[2011-01-23 19:18:41 +09:00]] 版)
<http://stackoverflow.com/questions/3932117/handling-http-contentencoding-deflate>

[8] [CITE@en-US[IE7 – Deflate or Not? – Subbu Allamaraju]]
([TIME[2015-08-05 00:10:34 +09:00]] 版)
<https://www.subbu.org/blog/2008/03/ie7-deflate-or-not>

[9] [CITE@ja[Deflate - Wikipedia]]
([TIME[2016-01-26 19:26:26 +09:00]] 版)
<https://ja.wikipedia.org/wiki/Deflate>

[10] [CITE@en[RFC 6713 - The 'application/zlib' and 'application/gzip' Media Types]]
([TIME[2015-09-27 13:20:11 +09:00]] 版)
<https://tools.ietf.org/html/rfc6713>


[FIG(quote)[
[FIGCAPTION[
[17] [CITE[Frequently Asked Questions about zlib]]
([TIME[2005-02-21 07:10:26 +09:00]] 版)
<http://www.gzip.org/zlib/zlib_faq.html#faq38>
]FIGCAPTION]

> "gzip" is the gzip format, and "deflate" is the zlib format. They should probably have called the second one "zlib" instead to avoid confusion with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 correctly points to the zlib specification in RFC 1950 for the "deflate" transfer encoding, there have been reports of servers and browsers that incorrectly produce or expect raw deflate data per the deflate specficiation in RFC 1951, most notably Microsoft. So even though the "deflate" transfer encoding using the zlib format would be the more efficient approach (and in fact exactly what the zlib format was designed for), using the "gzip" transfer encoding is probably more reliable due to an unfortunate choice of name on the part of the HTTP 1.1 authors.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[19] ([TIME[2017-06-20 10:35:40 +09:00]])
<http://cpansearch.perl.org/src/OALDERS/HTTP-Message-6.13/lib/HTTP/Message.pm>
]FIGCAPTION]

> 		    require IO::Uncompress::Inflate;
> 		    my $output;
> 		    my $status = IO::Uncompress::Inflate::inflate($content_ref, \$output, Transparent => 0);
> 		    my $error = $IO::Uncompress::Inflate::InflateError;
> 		    unless ($status) {
> 			# "Content-Encoding: deflate" is supposed to mean the
> 			# "zlib" format of RFC 1950, but Microsoft got that
> 			# wrong, so some servers sends the raw compressed
> 			# "deflate" data.  This tries to inflate this format.
> 			$output = undef;
> 			require IO::Uncompress::RawInflate;
> 			unless (IO::Uncompress::RawInflate::rawinflate($content_ref, \$output)) {
> 			    $self->push_header("Client-Warning" =>
> 				"Could not raw inflate content: $IO::Uncompress::RawInflate::RawInflateError");
> 			    $output = undef;
> 			}
> 		    }

]FIG]


[FIG(quote)[
[FIGCAPTION[
[63] [CITE@en[mod_deflate - Apache HTTP Server Version 2.4]]
([TIME[2017-03-29 06:54:20 +09:00]])
<http://httpd.apache.org/docs/current/en/mod/mod_deflate.html>
]FIGCAPTION]

> The deflate encoding is not supported, please check the zlib's documentation for a complete explanation.

]FIG]


[68] [CITE@en[Content-Encoding: deflate is actually zlib · Issue #46 · valyala/fasthttp]]
([TIME[2017-09-24 23:55:39 +09:00]])
<https://github.com/valyala/fasthttp/issues/46>

[69] [CITE@en[Re: Content-Encoding: deflate - is this zlib file format?]]
([[Daniel Barron]]著, [TIME[2001-09-09 22:17:24 +09:00]])
<https://lists.w3.org/Archives/Public/www-talk/2001SepOct/0015.html>