summaryrefslogtreecommitdiffstats
path: root/webkit/glue/ftp_directory_listing_response_delegate.cc
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-07-29 17:14:53 +0100
committerBen Murdoch <benm@google.com>2010-08-04 14:29:45 +0100
commitc407dc5cd9bdc5668497f21b26b09d988ab439de (patch)
tree7eaf8707c0309516bdb042ad976feedaf72b0bb1 /webkit/glue/ftp_directory_listing_response_delegate.cc
parent0998b1cdac5733f299c12d88bc31ef9c8035b8fa (diff)
downloadexternal_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.zip
external_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.tar.gz
external_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.tar.bz2
Merge Chromium src@r53293
Change-Id: Ia79acf8670f385cee48c45b0a75371d8e950af34
Diffstat (limited to 'webkit/glue/ftp_directory_listing_response_delegate.cc')
-rw-r--r--webkit/glue/ftp_directory_listing_response_delegate.cc159
1 files changed, 159 insertions, 0 deletions
diff --git a/webkit/glue/ftp_directory_listing_response_delegate.cc b/webkit/glue/ftp_directory_listing_response_delegate.cc
new file mode 100644
index 0000000..80737db
--- /dev/null
+++ b/webkit/glue/ftp_directory_listing_response_delegate.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/ftp_directory_listing_response_delegate.h"
+
+#include <vector>
+
+#include "base/i18n/icu_encoding_detection.h"
+#include "base/i18n/icu_string_conversions.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/time.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/ftp/ftp_directory_listing_parser.h"
+#include "net/ftp/ftp_server_type_histograms.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
+
+using net::FtpDirectoryListingEntry;
+
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderClient;
+using WebKit::WebURLResponse;
+
+namespace {
+
+string16 ConvertPathToUTF16(const std::string& path) {
+ // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII,
+ // but many old FTP servers use legacy encodings. Try UTF-8 first.
+ if (IsStringUTF8(path))
+ return UTF8ToUTF16(path);
+
+ // Try detecting the encoding. The sample is rather small though, so it may
+ // fail.
+ std::string encoding;
+ if (base::DetectEncoding(path, &encoding) && !encoding.empty()) {
+ string16 path_utf16;
+ if (base::CodepageToUTF16(path, encoding.c_str(),
+ base::OnStringConversionError::SUBSTITUTE,
+ &path_utf16)) {
+ return path_utf16;
+ }
+ }
+
+ // Use system native encoding as the last resort.
+ return WideToUTF16Hack(base::SysNativeMBToWide(path));
+}
+
+} // namespace
+
+namespace webkit_glue {
+
+FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate(
+ WebURLLoaderClient* client,
+ WebURLLoader* loader,
+ const WebURLResponse& response)
+ : client_(client),
+ loader_(loader),
+ original_response_(response),
+ buffer_(base::Time::Now()),
+ updated_histograms_(false),
+ had_parsing_error_(false) {
+ Init();
+}
+
+void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data,
+ int data_len) {
+ if (had_parsing_error_)
+ return;
+
+ if (buffer_.ConsumeData(data, data_len) == net::OK)
+ ProcessReceivedEntries();
+ else
+ had_parsing_error_ = true;
+}
+
+void FtpDirectoryListingResponseDelegate::OnCompletedRequest() {
+ if (!had_parsing_error_ && buffer_.ProcessRemainingData() == net::OK)
+ ProcessReceivedEntries();
+ else
+ had_parsing_error_ = true;
+
+ if (had_parsing_error_)
+ SendDataToClient("<script>onListingParsingError();</script>\n");
+}
+
+void FtpDirectoryListingResponseDelegate::Init() {
+ GURL response_url(original_response_.url());
+ UnescapeRule::Type unescape_rules = UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS;
+ std::string unescaped_path = UnescapeURLComponent(response_url.path(),
+ unescape_rules);
+ SendDataToClient(net::GetDirectoryListingHeader(
+ ConvertPathToUTF16(unescaped_path)));
+
+ // If this isn't top level directory (i.e. the path isn't "/",)
+ // add a link to the parent directory.
+ if (response_url.path().length() > 1) {
+ SendDataToClient(net::GetDirectoryListingEntry(
+ ASCIIToUTF16(".."), std::string(), false, 0, base::Time()));
+ }
+}
+
+bool FtpDirectoryListingResponseDelegate::ConvertToServerEncoding(
+ const string16& filename, std::string* raw_bytes) const {
+ if (buffer_.encoding().empty()) {
+ *raw_bytes = std::string();
+ return true;
+ }
+
+ return base::UTF16ToCodepage(filename, buffer_.encoding().c_str(),
+ base::OnStringConversionError::FAIL,
+ raw_bytes);
+}
+
+void FtpDirectoryListingResponseDelegate::ProcessReceivedEntries() {
+ if (!updated_histograms_ && buffer_.EntryAvailable()) {
+ // Only log the server type if we got enough data to reliably detect it.
+ net::UpdateFtpServerTypeHistograms(buffer_.GetServerType());
+ updated_histograms_ = true;
+ }
+
+ while (buffer_.EntryAvailable()) {
+ FtpDirectoryListingEntry entry = buffer_.PopEntry();
+
+ // Skip the current and parent directory entries in the listing. Our header
+ // always includes them.
+ if (EqualsASCII(entry.name, ".") || EqualsASCII(entry.name, ".."))
+ continue;
+
+ bool is_directory = (entry.type == FtpDirectoryListingEntry::DIRECTORY);
+ int64 size = entry.size;
+ if (entry.type != FtpDirectoryListingEntry::FILE)
+ size = 0;
+ std::string raw_bytes;
+ if (ConvertToServerEncoding(entry.name, &raw_bytes)) {
+ SendDataToClient(net::GetDirectoryListingEntry(
+ entry.name, raw_bytes, is_directory, size, entry.last_modified));
+ } else {
+ // Consider an encoding problem a non-fatal error. The server's support
+ // for non-ASCII characters might be buggy. Display an error message,
+ // but keep trying to display the rest of the listing (most file names
+ // are ASCII anyway, we could be just unlucky with this one).
+ had_parsing_error_ = true;
+ }
+ }
+}
+
+void FtpDirectoryListingResponseDelegate::SendDataToClient(
+ const std::string& data) {
+ client_->didReceiveData(loader_, data.data(), data.length());
+}
+
+} // namespace webkit_glue