1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/filter/gzip_header.h"
9 #include "base/logging.h"
10 #include "third_party/zlib/zlib.h"
14 const uint8
GZipHeader::magic
[] = { 0x1f, 0x8b };
16 GZipHeader::GZipHeader() {
20 GZipHeader::~GZipHeader() {
23 void GZipHeader::Reset() {
24 state_
= IN_HEADER_ID1
;
29 GZipHeader::Status
GZipHeader::ReadMore(const char* inbuf
, int inbuf_len
,
30 const char** header_end
) {
31 DCHECK_GE(inbuf_len
, 0);
32 const uint8
* pos
= reinterpret_cast<const uint8
*>(inbuf
);
33 const uint8
* const end
= pos
+ inbuf_len
;
38 if ( *pos
!= magic
[0] ) return INVALID_HEADER
;
43 if ( *pos
!= magic
[1] ) return INVALID_HEADER
;
48 if ( *pos
!= Z_DEFLATED
) return INVALID_HEADER
;
53 flags_
= (*pos
) & (FLAG_FHCRC
| FLAG_FEXTRA
|
54 FLAG_FNAME
| FLAG_FCOMMENT
);
59 case IN_HEADER_MTIME_BYTE_0
:
63 case IN_HEADER_MTIME_BYTE_1
:
67 case IN_HEADER_MTIME_BYTE_2
:
71 case IN_HEADER_MTIME_BYTE_3
:
87 if ( !(flags_
& FLAG_FEXTRA
) ) {
91 // We have a two-byte little-endian length, followed by a
92 // field of that length.
98 extra_length_
+= *pos
<< 8;
101 // We intentionally fall through, because if we have a
102 // zero-length FEXTRA, we want to check to notice that we're
103 // done reading the FEXTRA before we exit this loop...
106 // Grab the rest of the bytes in the extra field, or as many
107 // of them as are actually present so far.
108 const int num_extra_bytes
= static_cast<const int>(std::min(
109 static_cast<ptrdiff_t>(extra_length_
),
111 pos
+= num_extra_bytes
;
112 extra_length_
-= num_extra_bytes
;
113 if ( extra_length_
== 0 ) {
114 state_
= IN_FNAME
; // advance when we've seen extra_length_ bytes
115 flags_
&= ~FLAG_FEXTRA
; // we're done with the FEXTRA stuff
121 if ( !(flags_
& FLAG_FNAME
) ) {
122 state_
= IN_FCOMMENT
;
125 // See if we can find the end of the \0-terminated FNAME field.
126 pos
= reinterpret_cast<const uint8
*>(memchr(pos
, '\0', (end
- pos
)));
128 pos
++; // advance past the '\0'
129 flags_
&= ~FLAG_FNAME
; // we're done with the FNAME stuff
130 state_
= IN_FCOMMENT
;
132 pos
= end
; // everything we have so far is part of the FNAME
137 if ( !(flags_
& FLAG_FCOMMENT
) ) {
138 state_
= IN_FHCRC_BYTE_0
;
141 // See if we can find the end of the \0-terminated FCOMMENT field.
142 pos
= reinterpret_cast<const uint8
*>(memchr(pos
, '\0', (end
- pos
)));
144 pos
++; // advance past the '\0'
145 flags_
&= ~FLAG_FCOMMENT
; // we're done with the FCOMMENT stuff
146 state_
= IN_FHCRC_BYTE_0
;
148 pos
= end
; // everything we have so far is part of the FNAME
152 case IN_FHCRC_BYTE_0
:
153 if ( !(flags_
& FLAG_FHCRC
) ) {
161 case IN_FHCRC_BYTE_1
:
163 flags_
&= ~FLAG_FHCRC
; // we're done with the FHCRC stuff
168 *header_end
= reinterpret_cast<const char*>(pos
);
169 return COMPLETE_HEADER
;
173 if ( (state_
> IN_HEADER_OS
) && (flags_
== 0) ) {
174 *header_end
= reinterpret_cast<const char*>(pos
);
175 return COMPLETE_HEADER
;
177 return INCOMPLETE_HEADER
;