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

Side by Side Diff: webkit/glue/ftp_directory_listing_response_delegate.cc

Issue 343073: Use the new FTP LIST parsing code in the browser. (Closed)
Patch Set: fixes Created 11 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
« no previous file with comments | « webkit/glue/ftp_directory_listing_response_delegate.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "webkit/glue/ftp_directory_listing_response_delegate.h" 5 #include "webkit/glue/ftp_directory_listing_response_delegate.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/i18n/icu_string_conversions.h" 9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/sys_string_conversions.h" 12 #include "base/sys_string_conversions.h"
13 #include "base/time.h" 13 #include "base/time.h"
14 #include "net/base/escape.h" 14 #include "net/base/escape.h"
15 #include "net/base/net_errors.h"
15 #include "net/base/net_util.h" 16 #include "net/base/net_util.h"
17 #include "net/ftp/ftp_directory_listing_parsers.h"
16 #include "net/ftp/ftp_server_type_histograms.h" 18 #include "net/ftp/ftp_server_type_histograms.h"
17 #include "unicode/ucsdet.h" 19 #include "unicode/ucsdet.h"
18 #include "webkit/api/public/WebURL.h" 20 #include "webkit/api/public/WebURL.h"
19 #include "webkit/api/public/WebURLLoaderClient.h" 21 #include "webkit/api/public/WebURLLoaderClient.h"
20 22
21 using WebKit::WebURLLoader; 23 using WebKit::WebURLLoader;
22 using WebKit::WebURLLoaderClient; 24 using WebKit::WebURLLoaderClient;
23 using WebKit::WebURLResponse; 25 using WebKit::WebURLResponse;
24 26
25 namespace { 27 namespace {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 } // namespace 113 } // namespace
112 114
113 namespace webkit_glue { 115 namespace webkit_glue {
114 116
115 FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate( 117 FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate(
116 WebURLLoaderClient* client, 118 WebURLLoaderClient* client,
117 WebURLLoader* loader, 119 WebURLLoader* loader,
118 const WebURLResponse& response) 120 const WebURLResponse& response)
119 : client_(client), 121 : client_(client),
120 loader_(loader), 122 loader_(loader),
121 original_response_(response) { 123 original_response_(response),
124 parser_fallback_(false) {
122 Init(); 125 Init();
123 } 126 }
124 127
125 void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data, 128 void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data,
126 int data_len) { 129 int data_len) {
130 // Keep the raw data in case we have to use the old parser later.
127 input_buffer_.append(data, data_len); 131 input_buffer_.append(data, data_len);
128 132
133 if (!parser_fallback_) {
134 if (buffer_.ConsumeData(data, data_len) == net::OK)
135 return;
136 parser_fallback_ = true;
137 }
138
139 FeedFallbackParser();
140 SendResponseBufferToClient();
141 }
142
143 void FtpDirectoryListingResponseDelegate::OnCompletedRequest() {
144 if (!parser_fallback_) {
145 if (buffer_.ProcessRemainingData() == net::OK) {
146 while (buffer_.EntryAvailable())
147 AppendEntryToResponseBuffer(buffer_.PopEntry());
148 SendResponseBufferToClient();
149 net::UpdateFtpServerTypeHistograms(buffer_.GetServerType());
150 return;
151 }
152 parser_fallback_ = true;
153 }
154
155 FeedFallbackParser();
156 SendResponseBufferToClient();
157
158 // Only log the server type if we got enough data to reliably detect it.
159 if (parse_state_.parsed_one)
160 LogFtpServerType(parse_state_.lstyle);
161 }
162
163 void FtpDirectoryListingResponseDelegate::Init() {
164 memset(&parse_state_, 0, sizeof(parse_state_));
165
166 GURL response_url(original_response_.url());
167 UnescapeRule::Type unescape_rules = UnescapeRule::SPACES |
168 UnescapeRule::URL_SPECIAL_CHARS;
169 std::string unescaped_path = UnescapeURLComponent(response_url.path(),
170 unescape_rules);
171 string16 path_utf16;
172 // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII,
173 // but many old FTP servers use legacy encodings. Try UTF-8 first and
174 // detect the encoding.
175 if (IsStringUTF8(unescaped_path)) {
176 path_utf16 = UTF8ToUTF16(unescaped_path);
177 } else {
178 std::string encoding = DetectEncoding(unescaped_path);
179 // Try the detected encoding. If it fails, resort to the
180 // OS native encoding.
181 if (encoding.empty() ||
182 !base::CodepageToUTF16(unescaped_path, encoding.c_str(),
183 base::OnStringConversionError::SUBSTITUTE,
184 &path_utf16))
185 path_utf16 = WideToUTF16Hack(base::SysNativeMBToWide(unescaped_path));
186 }
187
188 response_buffer_ = net::GetDirectoryListingHeader(path_utf16);
189
190 // If this isn't top level directory (i.e. the path isn't "/",)
191 // add a link to the parent directory.
192 if (response_url.path().length() > 1) {
193 response_buffer_.append(
194 net::GetDirectoryListingEntry(ASCIIToUTF16(".."),
195 std::string(),
196 false, 0,
197 base::Time()));
198 }
199 }
200
201 void FtpDirectoryListingResponseDelegate::FeedFallbackParser() {
129 // If all we've seen so far is ASCII, encoding_ is empty. Try to detect the 202 // If all we've seen so far is ASCII, encoding_ is empty. Try to detect the
130 // encoding. We don't do the separate UTF-8 check here because the encoding 203 // encoding. We don't do the separate UTF-8 check here because the encoding
131 // detection with a longer chunk (as opposed to the relatively short path 204 // detection with a longer chunk (as opposed to the relatively short path
132 // component of the url) is unlikely to mistake UTF-8 for a legacy encoding. 205 // component of the url) is unlikely to mistake UTF-8 for a legacy encoding.
133 // If it turns out to be wrong, a separate UTF-8 check has to be added. 206 // If it turns out to be wrong, a separate UTF-8 check has to be added.
134 // 207 //
135 // TODO(jungshik): UTF-8 has to be 'enforced' without any heuristics when 208 // TODO(jungshik): UTF-8 has to be 'enforced' without any heuristics when
136 // we're talking to an FTP server compliant to RFC 2640 (that is, its response 209 // we're talking to an FTP server compliant to RFC 2640 (that is, its response
137 // to FEAT command includes 'UTF8'). 210 // to FEAT command includes 'UTF8').
138 // See http://wiki.filezilla-project.org/Character_Set 211 // See http://wiki.filezilla-project.org/Character_Set
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 } 263 }
191 break; 264 break;
192 case '?': // Junk entry. 265 case '?': // Junk entry.
193 case '"': // Comment entry. 266 case '"': // Comment entry.
194 break; 267 break;
195 default: 268 default:
196 NOTREACHED(); 269 NOTREACHED();
197 break; 270 break;
198 } 271 }
199 } 272 }
200
201 SendResponseBufferToClient();
202 } 273 }
203 274
204 void FtpDirectoryListingResponseDelegate::OnCompletedRequest() { 275 void FtpDirectoryListingResponseDelegate::AppendEntryToResponseBuffer(
205 SendResponseBufferToClient(); 276 const net::FtpDirectoryListingEntry& entry) {
206 277 switch (entry.type) {
207 // Only log the server type if we got enough data to reliably detect it. 278 case net::FtpDirectoryListingEntry::FILE:
208 if (parse_state_.parsed_one) 279 response_buffer_.append(
209 LogFtpServerType(parse_state_.lstyle); 280 net::GetDirectoryListingEntry(entry.name, std::string(), false,
210 } 281 entry.size, entry.last_modified));
211 282 break;
212 void FtpDirectoryListingResponseDelegate::Init() { 283 case net::FtpDirectoryListingEntry::DIRECTORY:
213 memset(&parse_state_, 0, sizeof(parse_state_)); 284 response_buffer_.append(
214 285 net::GetDirectoryListingEntry(entry.name, std::string(), true,
215 GURL response_url(original_response_.url()); 286 0, entry.last_modified));
216 UnescapeRule::Type unescape_rules = UnescapeRule::SPACES | 287 break;
217 UnescapeRule::URL_SPECIAL_CHARS; 288 case net::FtpDirectoryListingEntry::SYMLINK:
218 std::string unescaped_path = UnescapeURLComponent(response_url.path(), 289 response_buffer_.append(
219 unescape_rules); 290 net::GetDirectoryListingEntry(entry.name, std::string(), false,
220 string16 path_utf16; 291 0, entry.last_modified));
221 // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII, 292 break;
222 // but many old FTP servers use legacy encodings. Try UTF-8 first and 293 default:
223 // detect the encoding. 294 NOTREACHED();
224 if (IsStringUTF8(unescaped_path)) { 295 break;
225 path_utf16 = UTF8ToUTF16(unescaped_path);
226 } else {
227 std::string encoding = DetectEncoding(unescaped_path);
228 // Try the detected encoding. If it fails, resort to the
229 // OS native encoding.
230 if (encoding.empty() ||
231 !base::CodepageToUTF16(unescaped_path, encoding.c_str(),
232 base::OnStringConversionError::SUBSTITUTE,
233 &path_utf16))
234 path_utf16 = WideToUTF16Hack(base::SysNativeMBToWide(unescaped_path));
235 }
236
237 response_buffer_ = net::GetDirectoryListingHeader(path_utf16);
238
239 // If this isn't top level directory (i.e. the path isn't "/",)
240 // add a link to the parent directory.
241 if (response_url.path().length() > 1) {
242 response_buffer_.append(
243 net::GetDirectoryListingEntry(ASCIIToUTF16(".."),
244 std::string(),
245 false, 0,
246 base::Time()));
247 } 296 }
248 } 297 }
249 298
250 void FtpDirectoryListingResponseDelegate::SendResponseBufferToClient() { 299 void FtpDirectoryListingResponseDelegate::SendResponseBufferToClient() {
251 if (!response_buffer_.empty()) { 300 if (!response_buffer_.empty()) {
252 client_->didReceiveData(loader_, response_buffer_.data(), 301 client_->didReceiveData(loader_, response_buffer_.data(),
253 response_buffer_.length()); 302 response_buffer_.length());
254 response_buffer_.clear(); 303 response_buffer_.clear();
255 } 304 }
256 } 305 }
257 306
258 } // namespace webkit_glue 307 } // namespace webkit_glue
OLDNEW
« no previous file with comments | « webkit/glue/ftp_directory_listing_response_delegate.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698