| ... | ... | @@ -44,8 +44,11 @@ pub fn GzipStream(comptime ReaderType: type) type { |
| 44 | 44 | }, |
| 45 | 45 | |
| 46 | 46 | fn init(allocator: mem.Allocator, source: ReaderType) !Self { |
| 47 | var hasher = std.compress.hashedReader(source, std.hash.Crc32.init()); |
| 48 | const hashed_reader = hasher.reader(); |
| 49 | |
| 47 | 50 | // gzip header format is specified in RFC1952 |
| 48 | | const header = try source.readBytesNoEof(10); |
| 51 | const header = try hashed_reader.readBytesNoEof(10); |
| 49 | 52 | |
| 50 | 53 | // Check the ID1/ID2 fields |
| 51 | 54 | if (header[0] != 0x1f or header[1] != 0x8b) |
| ... | ... | @@ -66,31 +69,31 @@ pub fn GzipStream(comptime ReaderType: type) type { |
| 66 | 69 | _ = XFL; |
| 67 | 70 | |
| 68 | 71 | const extra = if (FLG & FEXTRA != 0) blk: { |
| 69 | | const len = try source.readIntLittle(u16); |
| 72 | const len = try hashed_reader.readIntLittle(u16); |
| 70 | 73 | const tmp_buf = try allocator.alloc(u8, len); |
| 71 | 74 | errdefer allocator.free(tmp_buf); |
| 72 | 75 | |
| 73 | | try source.readNoEof(tmp_buf); |
| 76 | try hashed_reader.readNoEof(tmp_buf); |
| 74 | 77 | break :blk tmp_buf; |
| 75 | 78 | } else null; |
| 76 | 79 | errdefer if (extra) |p| allocator.free(p); |
| 77 | 80 | |
| 78 | 81 | const filename = if (FLG & FNAME != 0) |
| 79 | | try source.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 82 | try hashed_reader.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 80 | 83 | else |
| 81 | 84 | null; |
| 82 | 85 | errdefer if (filename) |p| allocator.free(p); |
| 83 | 86 | |
| 84 | 87 | const comment = if (FLG & FCOMMENT != 0) |
| 85 | | try source.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 88 | try hashed_reader.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 86 | 89 | else |
| 87 | 90 | null; |
| 88 | 91 | errdefer if (comment) |p| allocator.free(p); |
| 89 | 92 | |
| 90 | 93 | if (FLG & FHCRC != 0) { |
| 91 | | // TODO: Evaluate and check the header checksum. The stdlib has |
| 92 | | // no CRC16 yet :( |
| 93 | | _ = try source.readIntLittle(u16); |
| 94 | const hash = try source.readIntLittle(u16); |
| 95 | if (hash != @truncate(u16, hasher.hasher.final())) |
| 96 | return error.WrongChecksum; |
| 94 | 97 | } |
| 95 | 98 | |
| 96 | 99 | return Self{ |
| ... | ... | @@ -230,3 +233,16 @@ test "sanity checks" { |
| 230 | 233 | }, ""), |
| 231 | 234 | ); |
| 232 | 235 | } |
| 236 | |
| 237 | test "header checksum" { |
| 238 | try testReader(&[_]u8{ |
| 239 | // GZIP header |
| 240 | 0x1f, 0x8b, 0x08, 0x12, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, |
| 241 | |
| 242 | // header.FHCRC (should cover entire header) |
| 243 | 0x99, 0xd6, |
| 244 | |
| 245 | // GZIP data |
| 246 | 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 247 | }, ""); |
| 248 | } |