summaryrefslogtreecommitdiffstats
path: root/chromium/content/child/ftp_directory_listing_response_delegate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/child/ftp_directory_listing_response_delegate.cc')
-rw-r--r--chromium/content/child/ftp_directory_listing_response_delegate.cc129
1 files changed, 129 insertions, 0 deletions
diff --git a/chromium/content/child/ftp_directory_listing_response_delegate.cc b/chromium/content/child/ftp_directory_listing_response_delegate.cc
new file mode 100644
index 00000000000..c3cc82705d9
--- /dev/null
+++ b/chromium/content/child/ftp_directory_listing_response_delegate.cc
@@ -0,0 +1,129 @@
+// Copyright 2014 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 "content/child/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/strings/string_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/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 "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "webkit/child/weburlresponse_extradata_impl.h"
+
+using blink::WebURLLoader;
+using blink::WebURLLoaderClient;
+using blink::WebURLResponse;
+using net::FtpDirectoryListingEntry;
+using webkit_glue::WebURLResponseExtraDataImpl;
+
+namespace {
+
+base::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 (base::IsStringUTF8(path))
+ return base::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()) {
+ base::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 base::WideToUTF16(base::SysNativeMBToWide(path));
+}
+
+} // namespace
+
+namespace content {
+
+FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate(
+ WebURLLoaderClient* client,
+ WebURLLoader* loader,
+ const WebURLResponse& response)
+ : client_(client),
+ loader_(loader) {
+ if (response.extraData()) {
+ // extraData can be NULL during tests.
+ WebURLResponseExtraDataImpl* extra_data =
+ static_cast<WebURLResponseExtraDataImpl*>(response.extraData());
+ extra_data->set_is_ftp_directory_listing(true);
+ }
+ Init(response.url());
+}
+
+void FtpDirectoryListingResponseDelegate::Cancel() {
+ client_ = NULL;
+ loader_ = NULL;
+}
+
+void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data,
+ int data_len) {
+ buffer_.append(data, data_len);
+}
+
+void FtpDirectoryListingResponseDelegate::OnCompletedRequest() {
+ std::vector<FtpDirectoryListingEntry> entries;
+ int rv = net::ParseFtpDirectoryListing(buffer_, base::Time::Now(), &entries);
+ if (rv != net::OK) {
+ SendDataToClient("<script>onListingParsingError();</script>\n");
+ return;
+ }
+ for (size_t i = 0; i < entries.size(); i++) {
+ const FtpDirectoryListingEntry& entry = entries[i];
+
+ // 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;
+ SendDataToClient(net::GetDirectoryListingEntry(
+ entry.name, entry.raw_name, is_directory, size, entry.last_modified));
+ }
+}
+
+void FtpDirectoryListingResponseDelegate::Init(const GURL& response_url) {
+ net::UnescapeRule::Type unescape_rules = net::UnescapeRule::SPACES |
+ net::UnescapeRule::URL_SPECIAL_CHARS;
+ std::string unescaped_path = net::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(
+ base::ASCIIToUTF16(".."), std::string(), false, 0, base::Time()));
+ }
+}
+
+void FtpDirectoryListingResponseDelegate::SendDataToClient(
+ const std::string& data) {
+ if (client_)
+ client_->didReceiveData(loader_, data.data(), data.length(), -1);
+}
+
+} // namespace content