| 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 |