@@ -257,7 +257,7 @@ local function get_obytestream(o)
257
257
elseif type (o ) == ' function' then
258
258
bs = o
259
259
else
260
- error (' unrecognized type: ' .. tostring (o ))
260
+ runtime_error (' unrecognized type: ' .. tostring (o ))
261
261
end
262
262
return bs
263
263
end
@@ -428,6 +428,35 @@ local function parse_gzip_header(bs)
428
428
end
429
429
end
430
430
431
+ local function parse_zlib_header (bs )
432
+ local cm = bs :read (4 ) -- Compression Method
433
+ local cinfo = bs :read (4 ) -- Compression info
434
+ local fcheck = bs :read (5 ) -- FLaGs: FCHECK (check bits for CMF and FLG)
435
+ local fdict = bs :read (1 ) -- FLaGs: FDICT (present dictionary)
436
+ local flevel = bs :read (2 ) -- FLaGs: FLEVEL (compression level)
437
+ local cmf = cinfo * 16 + cm -- CMF (Compresion Method and flags)
438
+ local flg = fcheck + fdict * 32 + flevel * 64 -- FLaGs
439
+
440
+ if cm ~= 8 then -- not "deflate"
441
+ runtime_error (" unrecognized zlib compression method: " + cm )
442
+ end
443
+ local window_size
444
+ if cinfo > 7 then
445
+ runtime_error (" invalid zlib window size: cinfo=" + cinfo )
446
+ end
447
+ local window_size = 2 ^ (cinfo + 8 )
448
+
449
+ if (cmf * 256 + flg ) % 31 ~= 0 then
450
+ runtime_error (" invalid zlib header (bad fcheck sum)" )
451
+ end
452
+
453
+ if fdict == 1 then
454
+ runtime_error (" FIX:TODO - FDICT not currently implemented" )
455
+ local dictid = bs :read (32 )
456
+ end
457
+
458
+ return window_size
459
+ end
431
460
432
461
local function parse_huffmantables (bs )
433
462
local hlit = bs :read (5 ) -- # of literal/length codes - 257
@@ -622,7 +651,7 @@ local function deflate(t)
622
651
end
623
652
M .deflate = deflate
624
653
625
-
654
+ -- http://tools.ietf.org/html/rfc1952
626
655
local function gunzip (t )
627
656
local bs = get_bitstream (t .input )
628
657
local outbs = get_obytestream (t .output )
@@ -643,14 +672,14 @@ local function gunzip(t)
643
672
644
673
bs :read (bs :nbits_left_in_byte ())
645
674
646
- local crc32 = bs :read (32 )
675
+ local expected_crc32 = bs :read (32 )
647
676
local isize = bs :read (32 ) -- ignored
648
677
if DEBUG then
649
- debug (' crc32=' , crc32 )
678
+ debug (' crc32=' , expected_crc32 )
650
679
debug (' isize=' , isize )
651
680
end
652
681
if not disable_crc and data_crc32 then
653
- if data_crc32 ~= crc32 then
682
+ if data_crc32 ~= expected_crc32 then
654
683
runtime_error (' invalid compressed data--crc error' )
655
684
end
656
685
end
@@ -660,6 +689,55 @@ local function gunzip(t)
660
689
end
661
690
M .gunzip = gunzip
662
691
692
+ -- adler32 checksum
693
+ -- see ADLER32 in http://tools.ietf.org/html/rfc1950 .
694
+ local function adler32 (byte , crc )
695
+ local s1 = crc % 65536
696
+ local s2 = (crc - s1 ) / 65536
697
+ s1 = (s1 + byte ) % 65521
698
+ s2 = (s2 + s1 ) % 65521
699
+ return s2 * 65536 + s1
700
+ end -- 65521 is the largest prime smaller than 2^16
701
+
702
+ -- http://tools.ietf.org/html/rfc1950
703
+ local function inflate_zlib (t )
704
+ local bs = get_bitstream (t .input )
705
+ local outbs = get_obytestream (t .output )
706
+ local disable_crc = t .disable_crc
707
+ if disable_crc == nil then disable_crc = false end
708
+
709
+ local window_size = parse_zlib_header (bs )
710
+
711
+ local data_adler32 = 1
712
+
713
+ deflate {input = bs , output =
714
+ disable_crc and outbs or
715
+ function (byte )
716
+ data_adler32 = adler32 (byte , data_adler32 )
717
+ outbs (byte )
718
+ end
719
+ }
720
+
721
+ bs :read (bs :nbits_left_in_byte ())
722
+
723
+ local b3 = bs :read (8 )
724
+ local b2 = bs :read (8 )
725
+ local b1 = bs :read (8 )
726
+ local b0 = bs :read (8 )
727
+ local expected_adler32 = ((b3 * 256 + b2 )* 256 + b1 )* 256 + b0
728
+ if DEBUG then
729
+ debug (' alder32=' , expected_adler32 )
730
+ end
731
+ if not disable_crc then
732
+ if data_adler32 ~= expected_adler32 then
733
+ runtime_error (' invalid compressed data--crc error' )
734
+ end
735
+ end
736
+ if bs :read () then
737
+ warn ' trailing garbage ignored'
738
+ end
739
+ end
740
+ M .inflate_zlib = inflate_zlib
663
741
664
742
return M
665
743
0 commit comments