summaryrefslogtreecommitdiffstats
path: root/net/ftp/ftp_directory_listing_parser.cc
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 07:26:52 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 07:26:52 +0000
commitda322acaebe30d84d9d8b6931752ab27333c3d36 (patch)
treec47effc5bec77fd099af537193fd0bff13a9629a /net/ftp/ftp_directory_listing_parser.cc
parent8ceea64ea9e45f97f2bac1df84e770ee23cca0e1 (diff)
downloadchromium_src-da322acaebe30d84d9d8b6931752ab27333c3d36.zip
chromium_src-da322acaebe30d84d9d8b6931752ab27333c3d36.tar.gz
chromium_src-da322acaebe30d84d9d8b6931752ab27333c3d36.tar.bz2
FTP: Multiple fixes for localized directory listings:
- fix detection of KOI8-R and possibly other encodings - fix parsing Russian month names When detecting the listing encoding, we need to not only check whether the data can be converted using given encoding, but also whether the result can be parsed as a valid directory listing. Also, we only need to compare the first three characters of the abbreviated month name, because that's how they're abbreviated in FTP directory listings. Finally, the Russian directory listings have swapped the "month" and "day of month" columns. BUG=65917 Review URL: http://codereview.chromium.org/6718043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80587 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/ftp/ftp_directory_listing_parser.cc')
-rw-r--r--net/ftp/ftp_directory_listing_parser.cc114
1 files changed, 65 insertions, 49 deletions
diff --git a/net/ftp/ftp_directory_listing_parser.cc b/net/ftp/ftp_directory_listing_parser.cc
index 8c36bb6..7d47725 100644
--- a/net/ftp/ftp_directory_listing_parser.cc
+++ b/net/ftp/ftp_directory_listing_parser.cc
@@ -16,93 +16,109 @@
#include "net/ftp/ftp_directory_listing_parser_windows.h"
#include "net/ftp/ftp_server_type_histograms.h"
-namespace {
-
-// Converts a string with unknown character encoding to UTF-16. On success
-// fills in |converted_text| and |encoding|. Returns network error code.
-int ConvertStringToUTF16(const std::string& text,
- string16* converted_text,
- std::string* encoding) {
- std::vector<std::string> encodings;
- if (!base::DetectAllEncodings(text, &encodings))
- return net::ERR_ENCODING_DETECTION_FAILED;
-
- // Use first encoding that can be used to decode the text.
- for (size_t i = 0; i < encodings.size(); i++) {
- if (base::CodepageToUTF16(text,
- encodings[i].c_str(),
- base::OnStringConversionError::FAIL,
- converted_text)) {
- *encoding = encodings[i];
- return net::OK;
- }
- }
+namespace net {
- return net::ERR_ENCODING_DETECTION_FAILED;
-}
+namespace {
+// Fills in |raw_name| for all |entries| using |encoding|. Returns network
+// error code.
int FillInRawName(const std::string& encoding,
- std::vector<net::FtpDirectoryListingEntry>* entries) {
+ std::vector<FtpDirectoryListingEntry>* entries) {
for (size_t i = 0; i < entries->size(); i++) {
if (!base::UTF16ToCodepage(entries->at(i).name, encoding.c_str(),
base::OnStringConversionError::FAIL,
&entries->at(i).raw_name)) {
- return net::ERR_ENCODING_CONVERSION_FAILED;
+ return ERR_ENCODING_CONVERSION_FAILED;
}
}
- return net::OK;
+ return OK;
}
-} // namespace
-
-namespace net {
-
-FtpDirectoryListingEntry::FtpDirectoryListingEntry() {
-}
-
-int ParseFtpDirectoryListing(const std::string& text,
- const base::Time& current_time,
- std::vector<FtpDirectoryListingEntry>* entries) {
- std::string encoding;
-
- string16 converted_text;
- int rv = ConvertStringToUTF16(text, &converted_text, &encoding);
- if (rv != OK)
- return rv;
-
+// Parses |text| as an FTP directory listing. Fills in |entries|
+// and |server_type| and returns network error code.
+int ParseListing(const string16& text,
+ const std::string& encoding,
+ const base::Time& current_time,
+ std::vector<FtpDirectoryListingEntry>* entries,
+ FtpServerType* server_type) {
std::vector<string16> lines;
- base::SplitString(converted_text, '\n', &lines);
+ base::SplitString(text, '\n', &lines);
// TODO(phajdan.jr): Use a table of callbacks instead of repeating code.
entries->clear();
if (ParseFtpDirectoryListingLs(lines, current_time, entries)) {
- UpdateFtpServerTypeHistograms(SERVER_LS);
+ *server_type = SERVER_LS;
return FillInRawName(encoding, entries);
}
entries->clear();
if (ParseFtpDirectoryListingWindows(lines, entries)) {
- UpdateFtpServerTypeHistograms(SERVER_WINDOWS);
+ *server_type = SERVER_WINDOWS;
return FillInRawName(encoding, entries);
}
entries->clear();
if (ParseFtpDirectoryListingVms(lines, entries)) {
- UpdateFtpServerTypeHistograms(SERVER_VMS);
+ *server_type = SERVER_VMS;
return FillInRawName(encoding, entries);
}
entries->clear();
if (ParseFtpDirectoryListingNetware(lines, current_time, entries)) {
- UpdateFtpServerTypeHistograms(SERVER_NETWARE);
+ *server_type = SERVER_NETWARE;
return FillInRawName(encoding, entries);
}
entries->clear();
- UpdateFtpServerTypeHistograms(SERVER_UNKNOWN);
+ return ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT;
+}
+
+// Detects encoding of |text| and parses it as an FTP directory listing.
+// Fills in |entries| and |server_type| and returns network error code.
+int DecodeAndParse(const std::string& text,
+ const base::Time& current_time,
+ std::vector<FtpDirectoryListingEntry>* entries,
+ FtpServerType* server_type) {
+ std::vector<std::string> encodings;
+ if (!base::DetectAllEncodings(text, &encodings))
+ return ERR_ENCODING_DETECTION_FAILED;
+
+ // Use first encoding that can be used to decode the text.
+ for (size_t i = 0; i < encodings.size(); i++) {
+ string16 converted_text;
+ if (base::CodepageToUTF16(text,
+ encodings[i].c_str(),
+ base::OnStringConversionError::FAIL,
+ &converted_text)) {
+ int rv = ParseListing(converted_text,
+ encodings[i],
+ current_time,
+ entries,
+ server_type);
+ if (rv == OK)
+ return rv;
+ }
+ }
+
+ entries->clear();
+ *server_type = SERVER_UNKNOWN;
return ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT;
}
} // namespace
+
+FtpDirectoryListingEntry::FtpDirectoryListingEntry() {
+}
+
+int ParseFtpDirectoryListing(const std::string& text,
+ const base::Time& current_time,
+ std::vector<FtpDirectoryListingEntry>* entries) {
+ FtpServerType server_type = SERVER_UNKNOWN;
+ int rv = DecodeAndParse(text, current_time, entries, &server_type);
+ UpdateFtpServerTypeHistograms(server_type);
+ return rv;
+}
+
+} // namespace net