Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: net/ftp/ftp_directory_listing_buffer.cc

Issue 4967001: FTP: improve character encoding detection in cases where ICU's first guess is wrong. (Closed)
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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::ConvertBufferToUTF16() {
81 const std::string& from, string16* to) { 82 if (encoding_.empty()) {
82 std::string encoding(encoding_.empty() ? "ascii" : encoding_); 83 std::vector<std::string> encodings;
83 return base::CodepageToUTF16(from, encoding.c_str(), 84 base::DetectAllEncodings(buffer_, &encodings);
84 base::OnStringConversionError::FAIL, to);
85 }
86 85
87 int FtpDirectoryListingBuffer::ExtractFullLinesFromBuffer() { 86 // Use first encoding that can be used to decode the buffer.
88 if (encoding_.empty()) { 87 for (size_t i = 0; i < encodings.size(); i++) {
89 if (!base::DetectEncoding(buffer_, &encoding_)) 88 string16 converted;
89 if (base::CodepageToUTF16(buffer_,
90 encodings[i].c_str(),
91 base::OnStringConversionError::FAIL,
92 &converted)) {
93 encoding_ = encodings[i];
94 break;
95 }
96 }
97
98 // If we haven't detected the encoding at this point, it's an error.
99 if (encoding_.empty())
90 return ERR_ENCODING_DETECTION_FAILED; 100 return ERR_ENCODING_DETECTION_FAILED;
eroman 2010/11/16 00:35:03 It seems prudent to clear converted_buffer_ before
Paweł Hajdan Jr. 2010/11/16 21:22:39 Skipped, as discussed offline.
91 } 101 }
92 102
103 string16 converted;
104 if (!base::CodepageToUTF16(buffer_,
eroman 2010/11/16 00:35:03 The structure of this function seems a little redu
Paweł Hajdan Jr. 2010/11/16 21:22:39 Done.
105 encoding_.c_str(),
106 base::OnStringConversionError::FAIL,
107 &converted))
108 return ERR_ENCODING_CONVERSION_FAILED;
109
110 buffer_.clear();
111 converted_buffer_ += converted;
112 return OK;
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
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
OLDNEW
« base/i18n/icu_encoding_detection.cc ('K') | « net/ftp/ftp_directory_listing_buffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698