1 // Copyright (c) 2006-2008 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. 4 5 // GZipFilter applies gzip and deflate content encoding/decoding to a data 6 // stream. As specified by HTTP 1.1, with gzip encoding the content is 7 // wrapped with a gzip header, and with deflate encoding the content is in 8 // a raw, headerless DEFLATE stream. 9 // 10 // Internally GZipFilter uses zlib inflate to do decoding. 11 // 12 // GZipFilter is a subclass of Filter. See the latter's header file filter.h 13 // for sample usage. 14 15 #ifndef NET_BASE_GZIP_FILTER_H__ 16 #define NET_BASE_GZIP_FILTER_H__ 17 18 #include "base/scoped_ptr.h" 19 #include "net/base/filter.h" 20 21 class GZipHeader; 22 typedef struct z_stream_s z_stream; 23 24 class GZipFilter : public Filter { 25 public: 26 explicit GZipFilter(const FilterContext& filter_context); 27 28 virtual ~GZipFilter(); 29 30 // Initializes filter decoding mode and internal control blocks. 31 // Parameter filter_type specifies the type of filter, which corresponds to 32 // either gzip or deflate decoding. The function returns true if success and 33 // false otherwise. 34 // The filter can only be initialized once. 35 bool InitDecoding(Filter::FilterType filter_type); 36 37 // Decodes the pre-filter data and writes the output into the dest_buffer 38 // passed in. 39 // The function returns FilterStatus. See filter.h for its description. 40 // 41 // Upon entry, *dest_len is the total size (in number of chars) of the 42 // destination buffer. Upon exit, *dest_len is the actual number of chars 43 // written into the destination buffer. 44 // 45 // This function will fail if there is no pre-filter data in the 46 // stream_buffer_. On the other hand, *dest_len can be 0 upon successful 47 // return. For example, the internal zlib may process some pre-filter data 48 // but not produce output yet. 49 virtual FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len); 50 51 private: 52 enum DecodingStatus { 53 DECODING_UNINITIALIZED, 54 DECODING_IN_PROGRESS, 55 DECODING_DONE, 56 DECODING_ERROR 57 }; 58 59 enum DecodingMode { 60 DECODE_MODE_GZIP, 61 DECODE_MODE_DEFLATE, 62 DECODE_MODE_UNKNOWN 63 }; 64 65 enum GZipCheckHeaderState { 66 GZIP_CHECK_HEADER_IN_PROGRESS, 67 GZIP_GET_COMPLETE_HEADER, 68 GZIP_GET_INVALID_HEADER 69 }; 70 71 static const int kGZipFooterSize = 8; 72 73 // Parses and verifies the GZip header. 74 // Upon exit, the function updates gzip_header_status_ accordingly. 75 // 76 // The function returns Filter::FILTER_OK if it gets a complete header and 77 // there are more data in the pre-filter buffer. 78 // The function returns Filter::FILTER_NEED_MORE_DATA if it parses all data 79 // in the pre-filter buffer, either getting a complete header or a partial 80 // header. The caller needs to check gzip_header_status_ and call this 81 // function again for partial header. 82 // The function returns Filter::FILTER_ERROR if error occurs. 83 FilterStatus CheckGZipHeader(); 84 85 // Internal function to decode the pre-filter data and writes the output into 86 // the dest_buffer passed in. 87 // 88 // This is the internal version of ReadFilteredData. See the latter's 89 // comments for the use of function. 90 FilterStatus DoInflate(char* dest_buffer, int* dest_len); 91 92 // Inserts a zlib header to the data stream before calling zlib inflate. 93 // This is used to work around server bugs. See more comments at the place 94 // it is called in gzip_filter.cc. 95 // The function returns true on success and false otherwise. 96 bool InsertZlibHeader(); 97 98 // Skip the 8 byte GZip footer after z_stream_end 99 void SkipGZipFooter(); 100 101 // Tracks the status of decoding. 102 // This variable is initialized by InitDecoding and updated only by 103 // ReadFilteredData. 104 DecodingStatus decoding_status_; 105 106 // Indicates the type of content decoding the GZipFilter is performing. 107 // This variable is set only once by InitDecoding. 108 DecodingMode decoding_mode_; 109 110 // Used to parse the gzip header in gzip stream. 111 // It is used when the decoding_mode_ is DECODE_MODE_GZIP. 112 scoped_ptr<GZipHeader> gzip_header_; 113 114 // Tracks the progress of parsing gzip header. 115 // This variable is maintained by gzip_header_. 116 GZipCheckHeaderState gzip_header_status_; 117 118 // A flag used by InsertZlibHeader to record whether we've successfully added 119 // a zlib header to this stream. 120 bool zlib_header_added_; 121 122 // Tracks how many bytes of gzip footer have been received. 123 int gzip_footer_bytes_; 124 125 // The control block of zlib which actually does the decoding. 126 // This data structure is initialized by InitDecoding and updated only by 127 // DoInflate, with InsertZlibHeader being the exception as a workaround. 128 scoped_ptr<z_stream> zlib_stream_; 129 130 // For robustness, when we see the solo sdch filter, we chain in a gzip filter 131 // in front of it, with this flag to indicate that the gzip decoding might not 132 // be needed. This handles a strange case where "Content-Encoding: sdch,gzip" 133 // is reduced by an errant proxy to "Content-Encoding: sdch", while the 134 // content is indeed really gzipped result of sdch :-/. 135 // If this flag is set, then we will revert to being a pass through filter if 136 // we don't get a valid gzip header. 137 bool possible_sdch_pass_through_; 138 139 DISALLOW_EVIL_CONSTRUCTORS(GZipFilter); 140 }; 141 142 #endif // NET_BASE_GZIP_FILTER_H__ 143