public GZIPHeader Clone() { var gheader = new GZIPHeader(); byte[] tmp; if (gheader.extra != null) { tmp = new byte[gheader.extra.Length]; Array.Copy(gheader.extra, 0, tmp, 0, tmp.Length); gheader.extra = tmp; } if (gheader.name != null) { tmp = new byte[gheader.name.Length]; Array.Copy(gheader.name, 0, tmp, 0, tmp.Length); gheader.name = tmp; } if (gheader.comment != null) { tmp = new byte[gheader.comment.Length]; Array.Copy(gheader.comment, 0, tmp, 0, tmp.Length); gheader.comment = tmp; } return(gheader); }
internal int Inflate_I(int f) { //int hold = 0; int r; int b; if (z == null || z.next_in == null) { if (f == Z_FINISH && this.mode == HEAD) { return(Z_OK); } return(Z_STREAM_ERROR); } f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; r = Z_BUF_ERROR; while (true) { if (mode == HEAD) { if (wrap == 0) { this.mode = BLOCKS; continue; // break; } try { r = ReadBytes(2, r, f); } catch (Return e) { return(e.r); } if ((wrap == 4 || (wrap & 2) != 0) && this.need == 0x8b1fL) // gzip header { if (wrap == 4) { wrap = 2; } z.adler = new CRC32(); Checksum(2, this.need); if (gheader == null) { gheader = new GZIPHeader(); } this.mode = FLAGS; continue; // break; } if ((wrap & 2) != 0) { this.mode = BAD; z.msg = "incorrect header check"; continue; // break; } flags = 0; this.method = ((int)this.need) & 0xff; b = ((int)(this.need >> 8)) & 0xff; if (((wrap & 1) == 0 || // check if zlib header allowed (((this.method << 8) + b) % 31) != 0) && (this.method & 0xf) != Z_DEFLATED) { if (wrap == 4) { z.next_in_index -= 2; z.avail_in += 2; z.total_in -= 2; wrap = 0; this.mode = BLOCKS; continue; // break; } this.mode = BAD; z.msg = "incorrect header check"; // since zlib 1.2, it is allowted to inflateSync for this case. /* * this.marker = 5; // can't try inflateSync */ continue; // break; } if ((this.method & 0xf) != Z_DEFLATED) { this.mode = BAD; z.msg = "unknown compression method"; // since zlib 1.2, it is allowted to inflateSync for this case. /* * this.marker = 5; // can't try inflateSync */ continue; // break; } if (wrap == 4) { wrap = 1; } if ((this.method >> 4) + 8 > this.wbits) { this.mode = BAD; z.msg = "invalid window size"; // since zlib 1.2, it is allowted to inflateSync for this case. /* * this.marker = 5; // can't try inflateSync */ continue; // break; } z.adler = new Adler32(); if ((b & PRESET_DICT) == 0) { this.mode = BLOCKS; continue; // break; } this.mode = DICT4; } // case HEAD if (this.mode == DICT4) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L; this.mode = DICT3; } // case DICT4 if (this.mode == DICT3) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L; this.mode = DICT2; } // case DICT3 if (this.mode == DICT2) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L; this.mode = DICT1; } // case DICT2 if (this.mode == DICT1) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += (z.next_in[z.next_in_index++] & 0xffL); z.adler.Reset(this.need); this.mode = DICT0; return(Z_NEED_DICT); } // case DICT1 if (this.mode == DICT0) { this.mode = BAD; z.msg = "need dictionary"; this.marker = 0; // can try inflateSync return(Z_STREAM_ERROR); } // case DICT0 if (this.mode == BLOCKS) { r = this.blocks.Proc(r); if (r == Z_DATA_ERROR) { this.mode = BAD; this.marker = 0; // can try inflateSync continue; // break; } if (r == Z_OK) { r = f; } if (r != Z_STREAM_END) { return(r); } r = f; this.was = z.adler.GetValue(); this.blocks.Reset(); if (this.wrap == 0) { this.mode = DONE; continue; // break; } this.mode = CHECK4; } // case BLOCKS if (this.mode == CHECK4) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L; this.mode = CHECK3; } // case CHECK4 if (this.mode == CHECK3) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L; this.mode = CHECK2; } // case CHECK3 if (this.mode == CHECK2) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L; this.mode = CHECK1; } // case CHECK2 if (this.mode == CHECK1) { if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; this.need += (z.next_in[z.next_in_index++] & 0xffL); if (flags != 0) { // gzip this.need = ((this.need & 0xff000000) >> 24 | (this.need & 0x00ff0000) >> 8 | (this.need & 0x0000ff00) << 8 | (this.need & 0x0000ffff) << 24) & 0xffffffffL; } if (((int)(this.was)) != ((int)(this.need))) { z.msg = "incorrect data check"; // chack is delayed /* * this.mode = BAD; * this.marker = 5; // can't try inflateSync * break; */ } else if (flags != 0 && gheader != null) { gheader.crc = this.need; } this.mode = LENGTH; } // case CHECK1 if (this.mode == LENGTH) { if (wrap != 0 && flags != 0) { try { r = ReadBytes(4, r, f); } catch (Return e) { return(e.r); } if (z.msg != null && z.msg.Equals("incorrect data check")) { this.mode = BAD; this.marker = 5; // can't try inflateSync continue; // break; } if (this.need != (z.total_out & 0xffffffffL)) { z.msg = "incorrect length check"; this.mode = BAD; continue; // break; } z.msg = null; } else { if (z.msg != null && z.msg.Equals("incorrect data check")) { this.mode = BAD; this.marker = 5; // can't try inflateSync continue; // break; } } this.mode = DONE; } // case LENGTH if (this.mode == DONE) { return(Z_STREAM_END); } if (this.mode == BAD) { return(Z_DATA_ERROR); } if (this.mode == FLAGS) { try { r = ReadBytes(2, r, f); } catch (Return e) { return(e.r); } flags = ((int)this.need) & 0xffff; if ((flags & 0xff) != Z_DEFLATED) { z.msg = "unknown compression method"; this.mode = BAD; continue; // break; } if ((flags & 0xe000) != 0) { z.msg = "unknown header flags set"; this.mode = BAD; continue; // break; } if ((flags & 0x0200) != 0) { Checksum(2, this.need); } this.mode = TIME; } // case FLAGS if (this.mode == TIME) { try { r = ReadBytes(4, r, f); } catch (Return e) { return(e.r); } if (gheader != null) { gheader.time = this.need; } if ((flags & 0x0200) != 0) { Checksum(4, this.need); } this.mode = OS; } // case TIME if (this.mode == OS) { try { r = ReadBytes(2, r, f); } catch (Return e) { return(e.r); } if (gheader != null) { gheader.xflags = ((int)this.need) & 0xff; gheader.os = (((int)this.need) >> 8) & 0xff; } if ((flags & 0x0200) != 0) { Checksum(2, this.need); } this.mode = EXLEN; } // case OS if (this.mode == EXLEN) { if ((flags & 0x0400) != 0) { try { r = ReadBytes(2, r, f); } catch (Return e) { return(e.r); } if (gheader != null) { gheader.extra = new byte[((int)this.need) & 0xffff]; } if ((flags & 0x0200) != 0) { Checksum(2, this.need); } } else if (gheader != null) { gheader.extra = null; } this.mode = EXTRA; } // case EXLEN if (this.mode == EXTRA) { if ((flags & 0x0400) != 0) { try { r = ReadBytes(r, f); if (gheader != null) { byte[] foo = tmp_string.ToArray(); tmp_string = null; if (foo.Length == gheader.extra.Length) { Array.Copy(foo, 0, gheader.extra, 0, foo.Length); } else { z.msg = "bad extra field length"; this.mode = BAD; continue; // break; } } } catch (Return e) { return(e.r); } } else if (gheader != null) { gheader.extra = null; } this.mode = NAME; } // case EXTRA if (this.mode == NAME) { if ((flags & 0x0800) != 0) { try { r = ReadString(r, f); if (gheader != null) { gheader.name = tmp_string.ToArray(); } tmp_string = null; } catch (Return e) { return(e.r); } } else if (gheader != null) { gheader.name = null; } this.mode = COMMENT; } // case NAME if (this.mode == COMMENT) { if ((flags & 0x1000) != 0) { try { r = ReadString(r, f); if (gheader != null) { gheader.comment = tmp_string.ToArray(); } tmp_string = null; } catch (Return e) { return(e.r); } } else if (gheader != null) { gheader.comment = null; } this.mode = HCRC; } // case COMMENT if (this.mode == HCRC) { if ((flags & 0x0200) != 0) { try { r = ReadBytes(2, r, f); } catch (Return e) { return(e.r); } if (gheader != null) { gheader.hcrc = (int)(this.need & 0xffff); } if (this.need != (z.adler.GetValue() & 0xffffL)) { this.mode = BAD; z.msg = "header crc mismatch"; this.marker = 5; // can't try inflateSync continue; // break; } } z.adler = new CRC32(); this.mode = BLOCKS; continue; // break; } // case HCRC // BAD // Default break; } // Default return(Z_STREAM_ERROR); }