This source file includes following definitions.
- Reset
- ReadMore
#include "net/filter/gzip_header.h"
#include <algorithm>
#include "base/logging.h"
#include "third_party/zlib/zlib.h"
namespace net {
const uint8 GZipHeader::magic[] = { 0x1f, 0x8b };
GZipHeader::GZipHeader() {
Reset();
}
GZipHeader::~GZipHeader() {
}
void GZipHeader::Reset() {
state_ = IN_HEADER_ID1;
flags_ = 0;
extra_length_ = 0;
}
GZipHeader::Status GZipHeader::ReadMore(const char* inbuf, int inbuf_len,
const char** header_end) {
DCHECK_GE(inbuf_len, 0);
const uint8* pos = reinterpret_cast<const uint8*>(inbuf);
const uint8* const end = pos + inbuf_len;
while ( pos < end ) {
switch ( state_ ) {
case IN_HEADER_ID1:
if ( *pos != magic[0] ) return INVALID_HEADER;
pos++;
state_++;
break;
case IN_HEADER_ID2:
if ( *pos != magic[1] ) return INVALID_HEADER;
pos++;
state_++;
break;
case IN_HEADER_CM:
if ( *pos != Z_DEFLATED ) return INVALID_HEADER;
pos++;
state_++;
break;
case IN_HEADER_FLG:
flags_ = (*pos) & (FLAG_FHCRC | FLAG_FEXTRA |
FLAG_FNAME | FLAG_FCOMMENT);
pos++;
state_++;
break;
case IN_HEADER_MTIME_BYTE_0:
pos++;
state_++;
break;
case IN_HEADER_MTIME_BYTE_1:
pos++;
state_++;
break;
case IN_HEADER_MTIME_BYTE_2:
pos++;
state_++;
break;
case IN_HEADER_MTIME_BYTE_3:
pos++;
state_++;
break;
case IN_HEADER_XFL:
pos++;
state_++;
break;
case IN_HEADER_OS:
pos++;
state_++;
break;
case IN_XLEN_BYTE_0:
if ( !(flags_ & FLAG_FEXTRA) ) {
state_ = IN_FNAME;
break;
}
extra_length_ = *pos;
pos++;
state_++;
break;
case IN_XLEN_BYTE_1:
extra_length_ += *pos << 8;
pos++;
state_++;
case IN_FEXTRA: {
const int num_extra_bytes = static_cast<const int>(std::min(
static_cast<ptrdiff_t>(extra_length_),
(end - pos)));
pos += num_extra_bytes;
extra_length_ -= num_extra_bytes;
if ( extra_length_ == 0 ) {
state_ = IN_FNAME;
flags_ &= ~FLAG_FEXTRA;
}
break;
}
case IN_FNAME:
if ( !(flags_ & FLAG_FNAME) ) {
state_ = IN_FCOMMENT;
break;
}
pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos)));
if ( pos != NULL ) {
pos++;
flags_ &= ~FLAG_FNAME;
state_ = IN_FCOMMENT;
} else {
pos = end;
}
break;
case IN_FCOMMENT:
if ( !(flags_ & FLAG_FCOMMENT) ) {
state_ = IN_FHCRC_BYTE_0;
break;
}
pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos)));
if ( pos != NULL ) {
pos++;
flags_ &= ~FLAG_FCOMMENT;
state_ = IN_FHCRC_BYTE_0;
} else {
pos = end;
}
break;
case IN_FHCRC_BYTE_0:
if ( !(flags_ & FLAG_FHCRC) ) {
state_ = IN_DONE;
break;
}
pos++;
state_++;
break;
case IN_FHCRC_BYTE_1:
pos++;
flags_ &= ~FLAG_FHCRC;
state_++;
break;
case IN_DONE:
*header_end = reinterpret_cast<const char*>(pos);
return COMPLETE_HEADER;
}
}
if ( (state_ > IN_HEADER_OS) && (flags_ == 0) ) {
*header_end = reinterpret_cast<const char*>(pos);
return COMPLETE_HEADER;
} else {
return INCOMPLETE_HEADER;
}
}
}