| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/ftp/ftp_directory_listing_buffer.h" | 5 #include "net/ftp/ftp_directory_listing_buffer.h" |
| 6 | 6 |
| 7 #include "base/i18n/icu_encoding_detection.h" | 7 #include "base/i18n/icu_encoding_detection.h" |
| 8 #include "base/i18n/icu_string_conversions.h" | 8 #include "base/i18n/icu_string_conversions.h" |
| 9 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 } | 30 } |
| 31 | 31 |
| 32 FtpDirectoryListingBuffer::~FtpDirectoryListingBuffer() { | 32 FtpDirectoryListingBuffer::~FtpDirectoryListingBuffer() { |
| 33 STLDeleteElements(&parsers_); | 33 STLDeleteElements(&parsers_); |
| 34 } | 34 } |
| 35 | 35 |
| 36 int FtpDirectoryListingBuffer::ConsumeData(const char* data, int data_length) { | 36 int FtpDirectoryListingBuffer::ConsumeData(const char* data, int data_length) { |
| 37 buffer_.append(data, data_length); | 37 buffer_.append(data, data_length); |
| 38 | 38 |
| 39 if (!encoding_.empty() || buffer_.length() > 1024) { | 39 if (!encoding_.empty() || buffer_.length() > 1024) { |
| 40 int rv = ExtractFullLinesFromBuffer(); | 40 int rv = ConsumeBuffer(); |
| 41 if (rv != OK) | 41 if (rv != OK) |
| 42 return rv; | 42 return rv; |
| 43 } | 43 } |
| 44 | 44 |
| 45 return ParseLines(); | 45 return ParseLines(); |
| 46 } | 46 } |
| 47 | 47 |
| 48 int FtpDirectoryListingBuffer::ProcessRemainingData() { | 48 int FtpDirectoryListingBuffer::ProcessRemainingData() { |
| 49 int rv = ExtractFullLinesFromBuffer(); | 49 int rv = ConsumeBuffer(); |
| 50 if (rv != OK) | 50 if (rv != OK) |
| 51 return rv; | 51 return rv; |
| 52 | 52 |
| 53 if (!buffer_.empty()) | 53 DCHECK(buffer_.empty()); |
| 54 if (!converted_buffer_.empty()) |
| 54 return ERR_INVALID_RESPONSE; | 55 return ERR_INVALID_RESPONSE; |
| 55 | 56 |
| 56 rv = ParseLines(); | 57 rv = ParseLines(); |
| 57 if (rv != OK) | 58 if (rv != OK) |
| 58 return rv; | 59 return rv; |
| 59 | 60 |
| 60 rv = OnEndOfInput(); | 61 rv = OnEndOfInput(); |
| 61 if (rv != OK) | 62 if (rv != OK) |
| 62 return rv; | 63 return rv; |
| 63 | 64 |
| 64 return OK; | 65 return OK; |
| 65 } | 66 } |
| 66 | 67 |
| 67 bool FtpDirectoryListingBuffer::EntryAvailable() const { | 68 bool FtpDirectoryListingBuffer::EntryAvailable() const { |
| 68 return (current_parser_ ? current_parser_->EntryAvailable() : false); | 69 return (current_parser_ ? current_parser_->EntryAvailable() : false); |
| 69 } | 70 } |
| 70 | 71 |
| 71 FtpDirectoryListingEntry FtpDirectoryListingBuffer::PopEntry() { | 72 FtpDirectoryListingEntry FtpDirectoryListingBuffer::PopEntry() { |
| 72 DCHECK(EntryAvailable()); | 73 DCHECK(EntryAvailable()); |
| 73 return current_parser_->PopEntry(); | 74 return current_parser_->PopEntry(); |
| 74 } | 75 } |
| 75 | 76 |
| 76 FtpServerType FtpDirectoryListingBuffer::GetServerType() const { | 77 FtpServerType FtpDirectoryListingBuffer::GetServerType() const { |
| 77 return (current_parser_ ? current_parser_->GetServerType() : SERVER_UNKNOWN); | 78 return (current_parser_ ? current_parser_->GetServerType() : SERVER_UNKNOWN); |
| 78 } | 79 } |
| 79 | 80 |
| 80 bool FtpDirectoryListingBuffer::ConvertToDetectedEncoding( | 81 int FtpDirectoryListingBuffer::DecodeBufferUsingEncoding( |
| 81 const std::string& from, string16* to) { | 82 const std::string& encoding) { |
| 82 std::string encoding(encoding_.empty() ? "ascii" : encoding_); | 83 string16 converted; |
| 83 return base::CodepageToUTF16(from, encoding.c_str(), | 84 if (!base::CodepageToUTF16(buffer_, |
| 84 base::OnStringConversionError::FAIL, to); | 85 encoding.c_str(), |
| 86 base::OnStringConversionError::FAIL, |
| 87 &converted)) |
| 88 return ERR_ENCODING_CONVERSION_FAILED; |
| 89 |
| 90 buffer_.clear(); |
| 91 converted_buffer_ += converted; |
| 92 return OK; |
| 85 } | 93 } |
| 86 | 94 |
| 87 int FtpDirectoryListingBuffer::ExtractFullLinesFromBuffer() { | 95 int FtpDirectoryListingBuffer::ConvertBufferToUTF16() { |
| 88 if (encoding_.empty()) { | 96 if (encoding_.empty()) { |
| 89 if (!base::DetectEncoding(buffer_, &encoding_)) | 97 std::vector<std::string> encodings; |
| 98 if (!base::DetectAllEncodings(buffer_, &encodings)) |
| 90 return ERR_ENCODING_DETECTION_FAILED; | 99 return ERR_ENCODING_DETECTION_FAILED; |
| 100 |
| 101 // Use first encoding that can be used to decode the buffer. |
| 102 for (size_t i = 0; i < encodings.size(); i++) { |
| 103 if (DecodeBufferUsingEncoding(encodings[i]) == OK) { |
| 104 encoding_ = encodings[i]; |
| 105 return OK; |
| 106 } |
| 107 } |
| 108 |
| 109 return ERR_ENCODING_DETECTION_FAILED; |
| 91 } | 110 } |
| 92 | 111 |
| 112 return DecodeBufferUsingEncoding(encoding_); |
| 113 } |
| 114 |
| 115 void FtpDirectoryListingBuffer::ExtractFullLinesFromBuffer() { |
| 93 int cut_pos = 0; | 116 int cut_pos = 0; |
| 94 // TODO(phajdan.jr): This code accepts all endlines matching \r*\n. Should it | 117 // TODO(phajdan.jr): This code accepts all endlines matching \r*\n. Should it |
| 95 // be more strict, or enforce consistent line endings? | 118 // be more strict, or enforce consistent line endings? |
| 96 for (size_t i = 0; i < buffer_.length(); ++i) { | 119 for (size_t i = 0; i < converted_buffer_.length(); ++i) { |
| 97 if (buffer_[i] != '\n') | 120 if (converted_buffer_[i] != '\n') |
| 98 continue; | 121 continue; |
| 99 int line_length = i - cut_pos; | 122 int line_length = i - cut_pos; |
| 100 if (i >= 1 && buffer_[i - 1] == '\r') | 123 if (i >= 1 && converted_buffer_[i - 1] == '\r') |
| 101 line_length--; | 124 line_length--; |
| 102 std::string line(buffer_.substr(cut_pos, line_length)); | 125 lines_.push_back(converted_buffer_.substr(cut_pos, line_length)); |
| 103 cut_pos = i + 1; | 126 cut_pos = i + 1; |
| 104 string16 line_converted; | |
| 105 if (!ConvertToDetectedEncoding(line, &line_converted)) { | |
| 106 buffer_.erase(0, cut_pos); | |
| 107 return ERR_ENCODING_CONVERSION_FAILED; | |
| 108 } | |
| 109 lines_.push_back(line_converted); | |
| 110 } | 127 } |
| 111 buffer_.erase(0, cut_pos); | 128 converted_buffer_.erase(0, cut_pos); |
| 129 } |
| 130 |
| 131 int FtpDirectoryListingBuffer::ConsumeBuffer() { |
| 132 int rv = ConvertBufferToUTF16(); |
| 133 if (rv != OK) |
| 134 return rv; |
| 135 |
| 136 ExtractFullLinesFromBuffer(); |
| 112 return OK; | 137 return OK; |
| 113 } | 138 } |
| 114 | 139 |
| 115 int FtpDirectoryListingBuffer::ParseLines() { | 140 int FtpDirectoryListingBuffer::ParseLines() { |
| 116 while (!lines_.empty()) { | 141 while (!lines_.empty()) { |
| 117 string16 line = lines_.front(); | 142 string16 line = lines_.front(); |
| 118 lines_.pop_front(); | 143 lines_.pop_front(); |
| 119 if (current_parser_) { | 144 if (current_parser_) { |
| 120 if (!current_parser_->ConsumeLine(line)) | 145 if (!current_parser_->ConsumeLine(line)) |
| 121 return ERR_FAILED; | 146 return ERR_FAILED; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 return OK; | 189 return OK; |
| 165 | 190 |
| 166 return ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT; | 191 return ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT; |
| 167 } | 192 } |
| 168 | 193 |
| 169 current_parser_ = *parsers_.begin(); | 194 current_parser_ = *parsers_.begin(); |
| 170 return OK; | 195 return OK; |
| 171 } | 196 } |
| 172 | 197 |
| 173 } // namespace net | 198 } // namespace net |
| OLD | NEW |