1%%% Utility functions for zlib. 2-module(yaws_zlib). 3-author('carsten@codimi.de'). 4 5 6-include("../include/yaws.hrl"). 7 8 9-export([gzipInit/1, gzipInit/2, gzipEnd/1, gzipDeflate/4, gzip/1, gzip/2]). 10 11 12gzipInit(Z) -> 13 gzipInit(Z, #deflate{}). 14 15gzipInit(Z, DOpts) -> 16 ok = zlib:deflateInit(Z, DOpts#deflate.compression_level, deflated, 17 DOpts#deflate.window_size, DOpts#deflate.mem_level, 18 DOpts#deflate.strategy), 19 undefined. 20 21 22gzipEnd(Z) -> 23 zlib:deflateEnd(Z). 24 25 26gzipDeflate(Z, undefined, Bin, Flush) -> 27 Crc32 = zlib:crc32(Z), 28 Head = << 29 % ID 30 16#1f, 16#8b, 31 % deflate 32 8:8, 33 % flags 34 0:8, 35 % mtime 36 0:32, 37 % xflags 38 0:8, 39 % OS_UNKNOWN 40 % Set to Unix instead? 41 255:8>>, 42 {ok, Priv, Bs} = gzipDeflate(Z, {Crc32,0}, Bin, Flush), 43 {ok, Priv, [Head | Bs]}; 44 45gzipDeflate(Z, {Crc32,Size}, Bin, Flush) -> 46 Bs = zlib:deflate(Z, Bin, Flush), 47 Crc1 = zlib:crc32(Z, Crc32, Bin), 48 Size1 = Size+size(Bin), 49 Data = 50 if 51 Flush == finish -> 52 % Appending should not 53 % hurt, so let's be a 54 % bit more consistent 55 % here. 56 Bs ++ [<<Crc1:32/little, Size1:32/little>>]; 57 true -> 58 Bs 59 end, 60 {ok, {Crc1, Size1}, Data}. 61 62 63%% like zlib:gzip/1, but returns an io list 64gzip(Data) -> 65 gzip(Data, #deflate{}). 66 67gzip(Data, DOpts) when is_binary(Data) -> 68 Z = zlib:open(), 69 {ok, _, D} = gzipDeflate(Z, gzipInit(Z, DOpts), Data, finish), 70 gzipEnd(Z), 71 zlib:close(Z), 72 {ok, D}; 73 74gzip(Data, DOpts) -> 75 Z = zlib:open(), 76 gzip_loop(Z, gzipInit(Z, DOpts), Data, [], []). 77 78gzip_loop(Z, P, [], [], A) -> 79 {ok, _, D} = gzipDeflate(Z, P, <<>>, finish), 80 gzipEnd(Z), 81 zlib:close(Z), 82 {ok, [A|D]}; 83gzip_loop(Z, P, B, C, A) when is_binary(B) -> 84 {ok, P1, D} = gzipDeflate(Z, P, B, none), 85 gzip_loop(Z, P1, C, [], 86 case D of 87 [] -> A; 88 _ -> 89 case A of 90 [] -> D; 91 _ -> [A|D] 92 end 93 end); 94gzip_loop(Z, P, [I|T], C, A) when is_integer(I) -> 95 gzip_loop(Z, P, list_to_binary([I|T]), C, A); 96gzip_loop(Z, P, [H], C, A) -> 97 gzip_loop(Z, P, H, C, A); 98gzip_loop(Z, P, [H|T], C, A) -> 99 gzip_loop(Z, P, H, [T|C], A); 100gzip_loop(Z, P, [], C, A) -> 101 gzip_loop(Z, P, C, [], A); 102gzip_loop(Z, P, I, C, A) when is_integer(I) -> 103 gzip_loop(Z, P, <<I>>, C, A). 104