OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/filter/gzip_filter.h" | 5 #include "net/filter/gzip_filter.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "net/filter/gzip_header.h" | 8 #include "net/filter/gzip_header.h" |
9 #include "third_party/zlib/zlib.h" | 9 #include "third_party/zlib/zlib.h" |
10 | 10 |
(...skipping 26 matching lines...) Expand all Loading... |
37 | 37 |
38 // Set decoding mode | 38 // Set decoding mode |
39 switch (filter_type) { | 39 switch (filter_type) { |
40 case Filter::FILTER_TYPE_DEFLATE: { | 40 case Filter::FILTER_TYPE_DEFLATE: { |
41 if (inflateInit(zlib_stream_.get()) != Z_OK) | 41 if (inflateInit(zlib_stream_.get()) != Z_OK) |
42 return false; | 42 return false; |
43 decoding_mode_ = DECODE_MODE_DEFLATE; | 43 decoding_mode_ = DECODE_MODE_DEFLATE; |
44 break; | 44 break; |
45 } | 45 } |
46 case Filter::FILTER_TYPE_GZIP_HELPING_SDCH: | 46 case Filter::FILTER_TYPE_GZIP_HELPING_SDCH: |
47 possible_sdch_pass_through_ = true; // Needed to optionally help sdch. | 47 possible_sdch_pass_through_ = true; // Needed to optionally help sdch. |
48 // Fall through to GZIP case. | 48 // Fall through to GZIP case. |
49 case Filter::FILTER_TYPE_GZIP: { | 49 case Filter::FILTER_TYPE_GZIP: { |
50 gzip_header_.reset(new GZipHeader()); | 50 gzip_header_.reset(new GZipHeader()); |
51 if (!gzip_header_.get()) | 51 if (!gzip_header_.get()) |
52 return false; | 52 return false; |
53 if (inflateInit2(zlib_stream_.get(), -MAX_WBITS) != Z_OK) | 53 if (inflateInit2(zlib_stream_.get(), -MAX_WBITS) != Z_OK) |
54 return false; | 54 return false; |
55 decoding_mode_ = DECODE_MODE_GZIP; | 55 decoding_mode_ = DECODE_MODE_GZIP; |
56 break; | 56 break; |
57 } | 57 } |
58 default: { | 58 default: { return false; } |
59 return false; | |
60 } | |
61 } | 59 } |
62 | 60 |
63 decoding_status_ = DECODING_IN_PROGRESS; | 61 decoding_status_ = DECODING_IN_PROGRESS; |
64 return true; | 62 return true; |
65 } | 63 } |
66 | 64 |
67 Filter::FilterStatus GZipFilter::ReadFilteredData(char* dest_buffer, | 65 Filter::FilterStatus GZipFilter::ReadFilteredData(char* dest_buffer, |
68 int* dest_len) { | 66 int* dest_len) { |
69 if (!dest_buffer || !dest_len || *dest_len <= 0) | 67 if (!dest_buffer || !dest_len || *dest_len <= 0) |
70 return Filter::FILTER_ERROR; | 68 return Filter::FILTER_ERROR; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 case Filter::FILTER_ERROR: { | 107 case Filter::FILTER_ERROR: { |
110 if (possible_sdch_pass_through_ && | 108 if (possible_sdch_pass_through_ && |
111 GZIP_GET_INVALID_HEADER == gzip_header_status_) { | 109 GZIP_GET_INVALID_HEADER == gzip_header_status_) { |
112 decoding_status_ = DECODING_DONE; // Become a pass through filter. | 110 decoding_status_ = DECODING_DONE; // Become a pass through filter. |
113 return CopyOut(dest_buffer, dest_len); | 111 return CopyOut(dest_buffer, dest_len); |
114 } | 112 } |
115 decoding_status_ = DECODING_ERROR; | 113 decoding_status_ = DECODING_ERROR; |
116 return status; | 114 return status; |
117 } | 115 } |
118 default: { | 116 default: { |
119 status = Filter::FILTER_ERROR; // Unexpected. | 117 status = Filter::FILTER_ERROR; // Unexpected. |
120 decoding_status_ = DECODING_ERROR; | 118 decoding_status_ = DECODING_ERROR; |
121 return status; | 119 return status; |
122 } | 120 } |
123 } | 121 } |
124 } | 122 } |
125 | 123 |
126 int dest_orig_size = *dest_len; | 124 int dest_orig_size = *dest_len; |
127 status = DoInflate(dest_buffer, dest_len); | 125 status = DoInflate(dest_buffer, dest_len); |
128 | 126 |
129 if (decoding_mode_ == DECODE_MODE_DEFLATE && status == Filter::FILTER_ERROR) { | 127 if (decoding_mode_ == DECODE_MODE_DEFLATE && status == Filter::FILTER_ERROR) { |
(...skipping 18 matching lines...) Expand all Loading... |
148 | 146 |
149 Filter::FilterStatus GZipFilter::CheckGZipHeader() { | 147 Filter::FilterStatus GZipFilter::CheckGZipHeader() { |
150 DCHECK_EQ(gzip_header_status_, GZIP_CHECK_HEADER_IN_PROGRESS); | 148 DCHECK_EQ(gzip_header_status_, GZIP_CHECK_HEADER_IN_PROGRESS); |
151 | 149 |
152 // Check input data in pre-filter buffer. | 150 // Check input data in pre-filter buffer. |
153 if (!next_stream_data_ || stream_data_len_ <= 0) | 151 if (!next_stream_data_ || stream_data_len_ <= 0) |
154 return Filter::FILTER_ERROR; | 152 return Filter::FILTER_ERROR; |
155 | 153 |
156 const char* header_end = NULL; | 154 const char* header_end = NULL; |
157 GZipHeader::Status header_status; | 155 GZipHeader::Status header_status; |
158 header_status = gzip_header_->ReadMore(next_stream_data_, stream_data_len_, | 156 header_status = |
159 &header_end); | 157 gzip_header_->ReadMore(next_stream_data_, stream_data_len_, &header_end); |
160 | 158 |
161 switch (header_status) { | 159 switch (header_status) { |
162 case GZipHeader::INCOMPLETE_HEADER: { | 160 case GZipHeader::INCOMPLETE_HEADER: { |
163 // We read all the data but only got a partial header. | 161 // We read all the data but only got a partial header. |
164 next_stream_data_ = NULL; | 162 next_stream_data_ = NULL; |
165 stream_data_len_ = 0; | 163 stream_data_len_ = 0; |
166 return Filter::FILTER_NEED_MORE_DATA; | 164 return Filter::FILTER_NEED_MORE_DATA; |
167 } | 165 } |
168 case GZipHeader::COMPLETE_HEADER: { | 166 case GZipHeader::COMPLETE_HEADER: { |
169 // We have a complete header. Check whether there are more data. | 167 // We have a complete header. Check whether there are more data. |
170 int num_chars_left = static_cast<int>(stream_data_len_ - | 168 int num_chars_left = |
171 (header_end - next_stream_data_)); | 169 static_cast<int>(stream_data_len_ - (header_end - next_stream_data_)); |
172 gzip_header_status_ = GZIP_GET_COMPLETE_HEADER; | 170 gzip_header_status_ = GZIP_GET_COMPLETE_HEADER; |
173 | 171 |
174 if (num_chars_left > 0) { | 172 if (num_chars_left > 0) { |
175 next_stream_data_ = const_cast<char*>(header_end); | 173 next_stream_data_ = const_cast<char*>(header_end); |
176 stream_data_len_ = num_chars_left; | 174 stream_data_len_ = num_chars_left; |
177 return Filter::FILTER_OK; | 175 return Filter::FILTER_OK; |
178 } else { | 176 } else { |
179 next_stream_data_ = NULL; | 177 next_stream_data_ = NULL; |
180 stream_data_len_ = 0; | 178 stream_data_len_ = 0; |
181 return Filter::FILTER_NEED_MORE_DATA; | 179 return Filter::FILTER_NEED_MORE_DATA; |
182 } | 180 } |
183 } | 181 } |
184 case GZipHeader::INVALID_HEADER: { | 182 case GZipHeader::INVALID_HEADER: { |
185 gzip_header_status_ = GZIP_GET_INVALID_HEADER; | 183 gzip_header_status_ = GZIP_GET_INVALID_HEADER; |
186 return Filter::FILTER_ERROR; | 184 return Filter::FILTER_ERROR; |
187 } | 185 } |
188 default: { | 186 default: { break; } |
189 break; | |
190 } | |
191 } | 187 } |
192 | 188 |
193 return Filter::FILTER_ERROR; | 189 return Filter::FILTER_ERROR; |
194 } | 190 } |
195 | 191 |
196 Filter::FilterStatus GZipFilter::DoInflate(char* dest_buffer, int* dest_len) { | 192 Filter::FilterStatus GZipFilter::DoInflate(char* dest_buffer, int* dest_len) { |
197 // Make sure we have both valid input data and output buffer. | 193 // Make sure we have both valid input data and output buffer. |
198 if (!dest_buffer || !dest_len || *dest_len <= 0) // output | 194 if (!dest_buffer || !dest_len || *dest_len <= 0) // output |
199 return Filter::FILTER_ERROR; | 195 return Filter::FILTER_ERROR; |
200 | 196 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 default: { | 250 default: { |
255 status = Filter::FILTER_ERROR; | 251 status = Filter::FILTER_ERROR; |
256 break; | 252 break; |
257 } | 253 } |
258 } | 254 } |
259 | 255 |
260 return status; | 256 return status; |
261 } | 257 } |
262 | 258 |
263 bool GZipFilter::InsertZlibHeader() { | 259 bool GZipFilter::InsertZlibHeader() { |
264 static char dummy_head[2] = { 0x78, 0x1 }; | 260 static char dummy_head[2] = {0x78, 0x1}; |
265 | 261 |
266 char dummy_output[4]; | 262 char dummy_output[4]; |
267 | 263 |
268 // We only try add additional header once. | 264 // We only try add additional header once. |
269 if (zlib_header_added_) | 265 if (zlib_header_added_) |
270 return false; | 266 return false; |
271 | 267 |
272 inflateReset(zlib_stream_.get()); | 268 inflateReset(zlib_stream_.get()); |
273 zlib_stream_.get()->next_in = bit_cast<Bytef*>(&dummy_head[0]); | 269 zlib_stream_.get()->next_in = bit_cast<Bytef*>(&dummy_head[0]); |
274 zlib_stream_.get()->avail_in = sizeof(dummy_head); | 270 zlib_stream_.get()->avail_in = sizeof(dummy_head); |
275 zlib_stream_.get()->next_out = bit_cast<Bytef*>(&dummy_output[0]); | 271 zlib_stream_.get()->next_out = bit_cast<Bytef*>(&dummy_output[0]); |
276 zlib_stream_.get()->avail_out = sizeof(dummy_output); | 272 zlib_stream_.get()->avail_out = sizeof(dummy_output); |
277 | 273 |
278 int code = inflate(zlib_stream_.get(), Z_NO_FLUSH); | 274 int code = inflate(zlib_stream_.get(), Z_NO_FLUSH); |
279 zlib_header_added_ = true; | 275 zlib_header_added_ = true; |
280 | 276 |
281 return (code == Z_OK); | 277 return (code == Z_OK); |
282 } | 278 } |
283 | 279 |
284 | |
285 void GZipFilter::SkipGZipFooter() { | 280 void GZipFilter::SkipGZipFooter() { |
286 int footer_bytes_expected = kGZipFooterSize - gzip_footer_bytes_; | 281 int footer_bytes_expected = kGZipFooterSize - gzip_footer_bytes_; |
287 if (footer_bytes_expected > 0) { | 282 if (footer_bytes_expected > 0) { |
288 int footer_byte_avail = std::min(footer_bytes_expected, stream_data_len_); | 283 int footer_byte_avail = std::min(footer_bytes_expected, stream_data_len_); |
289 stream_data_len_ -= footer_byte_avail; | 284 stream_data_len_ -= footer_byte_avail; |
290 next_stream_data_ += footer_byte_avail; | 285 next_stream_data_ += footer_byte_avail; |
291 gzip_footer_bytes_ += footer_byte_avail; | 286 gzip_footer_bytes_ += footer_byte_avail; |
292 | 287 |
293 if (stream_data_len_ == 0) | 288 if (stream_data_len_ == 0) |
294 next_stream_data_ = NULL; | 289 next_stream_data_ = NULL; |
295 } | 290 } |
296 } | 291 } |
297 | 292 |
298 } // namespace net | 293 } // namespace net |
OLD | NEW |