OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 // Derived from: | 5 // Derived from: |
6 // mozilla/netwerk/protocol/http/src/nsHttpChunkedDecoder.cpp | 6 // mozilla/netwerk/protocol/http/src/nsHttpChunkedDecoder.cpp |
7 // The license block is: | 7 // The license block is: |
8 /* ***** BEGIN LICENSE BLOCK ***** | 8 /* ***** BEGIN LICENSE BLOCK ***** |
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
10 * | 10 * |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 if (!chunk_remaining_) | 83 if (!chunk_remaining_) |
84 chunk_terminator_remaining_ = true; | 84 chunk_terminator_remaining_ = true; |
85 continue; | 85 continue; |
86 } else if (reached_eof_) { | 86 } else if (reached_eof_) { |
87 bytes_after_eof_ += buf_len; | 87 bytes_after_eof_ += buf_len; |
88 break; // Done! | 88 break; // Done! |
89 } | 89 } |
90 | 90 |
91 int bytes_consumed = ScanForChunkRemaining(buf, buf_len); | 91 int bytes_consumed = ScanForChunkRemaining(buf, buf_len); |
92 if (bytes_consumed < 0) | 92 if (bytes_consumed < 0) |
93 return bytes_consumed; // Error | 93 return bytes_consumed; // Error |
94 | 94 |
95 buf_len -= bytes_consumed; | 95 buf_len -= bytes_consumed; |
96 if (buf_len) | 96 if (buf_len) |
97 memmove(buf, buf + bytes_consumed, buf_len); | 97 memmove(buf, buf + bytes_consumed, buf_len); |
98 } | 98 } |
99 | 99 |
100 return result; | 100 return result; |
101 } | 101 } |
102 | 102 |
103 int HttpChunkedDecoder::ScanForChunkRemaining(const char* buf, int buf_len) { | 103 int HttpChunkedDecoder::ScanForChunkRemaining(const char* buf, int buf_len) { |
(...skipping 27 matching lines...) Expand all Loading... |
131 return ERR_INVALID_CHUNKED_ENCODING; | 131 return ERR_INVALID_CHUNKED_ENCODING; |
132 } | 132 } |
133 chunk_terminator_remaining_ = false; | 133 chunk_terminator_remaining_ = false; |
134 } else if (buf_len) { | 134 } else if (buf_len) { |
135 // Ignore any chunk-extensions. | 135 // Ignore any chunk-extensions. |
136 size_t index_of_semicolon = base::StringPiece(buf, buf_len).find(';'); | 136 size_t index_of_semicolon = base::StringPiece(buf, buf_len).find(';'); |
137 if (index_of_semicolon != base::StringPiece::npos) | 137 if (index_of_semicolon != base::StringPiece::npos) |
138 buf_len = static_cast<int>(index_of_semicolon); | 138 buf_len = static_cast<int>(index_of_semicolon); |
139 | 139 |
140 if (!ParseChunkSize(buf, buf_len, &chunk_remaining_)) { | 140 if (!ParseChunkSize(buf, buf_len, &chunk_remaining_)) { |
141 DLOG(ERROR) << "Failed parsing HEX from: " << | 141 DLOG(ERROR) << "Failed parsing HEX from: " << std::string(buf, buf_len); |
142 std::string(buf, buf_len); | |
143 return ERR_INVALID_CHUNKED_ENCODING; | 142 return ERR_INVALID_CHUNKED_ENCODING; |
144 } | 143 } |
145 | 144 |
146 if (chunk_remaining_ == 0) | 145 if (chunk_remaining_ == 0) |
147 reached_last_chunk_ = true; | 146 reached_last_chunk_ = true; |
148 } else { | 147 } else { |
149 DLOG(ERROR) << "missing chunk-size"; | 148 DLOG(ERROR) << "missing chunk-size"; |
150 return ERR_INVALID_CHUNKED_ENCODING; | 149 return ERR_INVALID_CHUNKED_ENCODING; |
151 } | 150 } |
152 line_buf_.clear(); | 151 line_buf_.clear(); |
153 } else { | 152 } else { |
154 // Save the partial line; wait for more data. | 153 // Save the partial line; wait for more data. |
155 bytes_consumed = buf_len; | 154 bytes_consumed = buf_len; |
156 | 155 |
157 // Ignore a trailing CR | 156 // Ignore a trailing CR |
158 if (buf[buf_len - 1] == '\r') | 157 if (buf[buf_len - 1] == '\r') |
159 buf_len--; | 158 buf_len--; |
160 | 159 |
161 if (line_buf_.length() + buf_len > kMaxLineBufLen) { | 160 if (line_buf_.length() + buf_len > kMaxLineBufLen) { |
162 DLOG(ERROR) << "Chunked line length too long"; | 161 DLOG(ERROR) << "Chunked line length too long"; |
163 return ERR_INVALID_CHUNKED_ENCODING; | 162 return ERR_INVALID_CHUNKED_ENCODING; |
164 } | 163 } |
165 | 164 |
166 line_buf_.append(buf, buf_len); | 165 line_buf_.append(buf, buf_len); |
167 } | 166 } |
168 return bytes_consumed; | 167 return bytes_consumed; |
169 } | 168 } |
170 | 169 |
171 | |
172 // While the HTTP 1.1 specification defines chunk-size as 1*HEX | 170 // While the HTTP 1.1 specification defines chunk-size as 1*HEX |
173 // some sites rely on more lenient parsing. | 171 // some sites rely on more lenient parsing. |
174 // http://www.yahoo.com/, for example, pads chunk-size with trailing spaces | 172 // http://www.yahoo.com/, for example, pads chunk-size with trailing spaces |
175 // (0x20) to be 7 characters long, such as "819b ". | 173 // (0x20) to be 7 characters long, such as "819b ". |
176 // | 174 // |
177 // A comparison of browsers running on WindowsXP shows that | 175 // A comparison of browsers running on WindowsXP shows that |
178 // they will parse the following inputs (egrep syntax): | 176 // they will parse the following inputs (egrep syntax): |
179 // | 177 // |
180 // Let \X be the character class for a hex digit: [0-9a-fA-F] | 178 // Let \X be the character class for a hex digit: [0-9a-fA-F] |
181 // | 179 // |
(...skipping 10 matching lines...) Expand all Loading... |
192 bool HttpChunkedDecoder::ParseChunkSize(const char* start, int len, int* out) { | 190 bool HttpChunkedDecoder::ParseChunkSize(const char* start, int len, int* out) { |
193 DCHECK_GE(len, 0); | 191 DCHECK_GE(len, 0); |
194 | 192 |
195 // Strip trailing spaces | 193 // Strip trailing spaces |
196 while (len && start[len - 1] == ' ') | 194 while (len && start[len - 1] == ' ') |
197 len--; | 195 len--; |
198 | 196 |
199 // Be more restrictive than HexStringToInt; | 197 // Be more restrictive than HexStringToInt; |
200 // don't allow inputs with leading "-", "+", "0x", "0X" | 198 // don't allow inputs with leading "-", "+", "0x", "0X" |
201 base::StringPiece chunk_size(start, len); | 199 base::StringPiece chunk_size(start, len); |
202 if (chunk_size.find_first_not_of("0123456789abcdefABCDEF") | 200 if (chunk_size.find_first_not_of("0123456789abcdefABCDEF") != |
203 != base::StringPiece::npos) { | 201 base::StringPiece::npos) { |
204 return false; | 202 return false; |
205 } | 203 } |
206 | 204 |
207 int parsed_number; | 205 int parsed_number; |
208 bool ok = base::HexStringToInt(chunk_size, &parsed_number); | 206 bool ok = base::HexStringToInt(chunk_size, &parsed_number); |
209 if (ok && parsed_number >= 0) { | 207 if (ok && parsed_number >= 0) { |
210 *out = parsed_number; | 208 *out = parsed_number; |
211 return true; | 209 return true; |
212 } | 210 } |
213 return false; | 211 return false; |
214 } | 212 } |
215 | 213 |
216 } // namespace net | 214 } // namespace net |
OLD | NEW |