1 // Copyright (c) 2011 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/base/gzip_header.h"
7 #include "base/logging.h"
8 #include "third_party/zlib/zlib.h"
12 const uint8
GZipHeader::magic
[] = { 0x1f, 0x8b };
14 GZipHeader::GZipHeader() {
18 GZipHeader::~GZipHeader() {
21 void GZipHeader::Reset() {
22 state_
= IN_HEADER_ID1
;
27 GZipHeader::Status
GZipHeader::ReadMore(const char* inbuf
, int inbuf_len
,
28 const char** header_end
) {
29 DCHECK_GE(inbuf_len
, 0);
30 const uint8
* pos
= reinterpret_cast<const uint8
*>(inbuf
);
31 const uint8
* const end
= pos
+ inbuf_len
;
36 if ( *pos
!= magic
[0] ) return INVALID_HEADER
;
41 if ( *pos
!= magic
[1] ) return INVALID_HEADER
;
46 if ( *pos
!= Z_DEFLATED
) return INVALID_HEADER
;
51 flags_
= (*pos
) & (FLAG_FHCRC
| FLAG_FEXTRA
|
52 FLAG_FNAME
| FLAG_FCOMMENT
);
57 case IN_HEADER_MTIME_BYTE_0
:
61 case IN_HEADER_MTIME_BYTE_1
:
65 case IN_HEADER_MTIME_BYTE_2
:
69 case IN_HEADER_MTIME_BYTE_3
:
85 if ( !(flags_
& FLAG_FEXTRA
) ) {
89 // We have a two-byte little-endian length, followed by a
90 // field of that length.
96 extra_length_
+= *pos
<< 8;
99 // We intentionally fall through, because if we have a
100 // zero-length FEXTRA, we want to check to notice that we're
101 // done reading the FEXTRA before we exit this loop...
104 // Grab the rest of the bytes in the extra field, or as many
105 // of them as are actually present so far.
106 const int num_extra_bytes
= static_cast<const int>(std::min(
107 static_cast<ptrdiff_t>(extra_length_
),
109 pos
+= num_extra_bytes
;
110 extra_length_
-= num_extra_bytes
;
111 if ( extra_length_
== 0 ) {
112 state_
= IN_FNAME
; // advance when we've seen extra_length_ bytes
113 flags_
&= ~FLAG_FEXTRA
; // we're done with the FEXTRA stuff
119 if ( !(flags_
& FLAG_FNAME
) ) {
120 state_
= IN_FCOMMENT
;
123 // See if we can find the end of the \0-terminated FNAME field.
124 pos
= reinterpret_cast<const uint8
*>(memchr(pos
, '\0', (end
- pos
)));
126 pos
++; // advance past the '\0'
127 flags_
&= ~FLAG_FNAME
; // we're done with the FNAME stuff
128 state_
= IN_FCOMMENT
;
130 pos
= end
; // everything we have so far is part of the FNAME
135 if ( !(flags_
& FLAG_FCOMMENT
) ) {
136 state_
= IN_FHCRC_BYTE_0
;
139 // See if we can find the end of the \0-terminated FCOMMENT field.
140 pos
= reinterpret_cast<const uint8
*>(memchr(pos
, '\0', (end
- pos
)));
142 pos
++; // advance past the '\0'
143 flags_
&= ~FLAG_FCOMMENT
; // we're done with the FCOMMENT stuff
144 state_
= IN_FHCRC_BYTE_0
;
146 pos
= end
; // everything we have so far is part of the FNAME
150 case IN_FHCRC_BYTE_0
:
151 if ( !(flags_
& FLAG_FHCRC
) ) {
159 case IN_FHCRC_BYTE_1
:
161 flags_
&= ~FLAG_FHCRC
; // we're done with the FHCRC stuff
166 *header_end
= reinterpret_cast<const char*>(pos
);
167 return COMPLETE_HEADER
;
171 if ( (state_
> IN_HEADER_OS
) && (flags_
== 0) ) {
172 *header_end
= reinterpret_cast<const char*>(pos
);
173 return COMPLETE_HEADER
;
175 return INCOMPLETE_HEADER
;