diff options
-rw-r--r-- | net/ftp/ftp_directory_listing_parser_ls.cc | 18 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_parser_windows.cc | 11 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_parser_windows_unittest.cc | 3 | ||||
-rw-r--r-- | net/ftp/ftp_util.cc | 19 | ||||
-rw-r--r-- | net/ftp/ftp_util.h | 4 | ||||
-rw-r--r-- | net/ftp/ftp_util_unittest.cc | 27 |
6 files changed, 62 insertions, 20 deletions
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc index c7c4326..1098cda 100644 --- a/net/ftp/ftp_directory_listing_parser_ls.cc +++ b/net/ftp/ftp_directory_listing_parser_ls.cc @@ -42,22 +42,6 @@ bool LooksLikeUnixPermissionsListing(const string16& text) { (text.substr(10).empty() || text.substr(10) == ASCIIToUTF16("+"))); } -string16 GetStringPartAfterColumns(const string16& text, int columns) { - DCHECK_LE(1, columns); - int columns_so_far = 0; - size_t last = 0; - for (size_t i = 1; i < text.length(); ++i) { - if (!isspace(text[i - 1]) && isspace(text[i])) { - last = i; - if (++columns_so_far == columns) - break; - } - } - string16 result(text.substr(last)); - TrimWhitespace(result, TRIM_ALL, &result); - return result; -} - bool DetectColumnOffset(const std::vector<string16>& columns, int* offset) { base::Time time; @@ -164,7 +148,7 @@ bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) { return false; } - entry.name = GetStringPartAfterColumns(line, 6 + column_offset); + entry.name = FtpUtil::GetStringPartAfterColumns(line, 6 + column_offset); if (entry.type == FtpDirectoryListingEntry::SYMLINK) { string16::size_type pos = entry.name.rfind(ASCIIToUTF16(" -> ")); if (pos == string16::npos) diff --git a/net/ftp/ftp_directory_listing_parser_windows.cc b/net/ftp/ftp_directory_listing_parser_windows.cc index 3f2818e..85ae6d5 100644 --- a/net/ftp/ftp_directory_listing_parser_windows.cc +++ b/net/ftp/ftp_directory_listing_parser_windows.cc @@ -7,12 +7,13 @@ #include <vector> #include "base/string_util.h" +#include "net/ftp/ftp_util.h" namespace { bool WindowsDateListingToTime(const std::vector<string16>& columns, base::Time* time) { - DCHECK_EQ(4U, columns.size()); + DCHECK_LE(4U, columns.size()); base::Time::Exploded time_exploded = { 0 }; @@ -68,11 +69,15 @@ FtpDirectoryListingParserWindows::FtpDirectoryListingParserWindows() { bool FtpDirectoryListingParserWindows::ConsumeLine(const string16& line) { std::vector<string16> columns; SplitString(CollapseWhitespace(line, false), ' ', &columns); - if (columns.size() != 4) + + // We may receive file names containing spaces, which can make the number of + // columns arbitrarily large. We will handle that later. For now just make + // sure we have all the columns that should normally be there. + if (columns.size() < 4) return false; FtpDirectoryListingEntry entry; - entry.name = columns[3]; + entry.name = FtpUtil::GetStringPartAfterColumns(line, 3); if (EqualsASCII(columns[2], "<DIR>")) { entry.type = FtpDirectoryListingEntry::DIRECTORY; diff --git a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc index 57fd216..bbab699 100644 --- a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc @@ -46,6 +46,9 @@ TEST_F(FtpDirectoryListingParserWindowsTest, Good) { { "01-06-1979 02:42AM 458 Readme.txt", net::FtpDirectoryListingEntry::FILE, "Readme.txt", 458, 1979, 1, 6, 2, 42 }, + { "11-02-09 05:32PM <DIR> My Directory", + net::FtpDirectoryListingEntry::DIRECTORY, "My Directory", -1, + 2009, 11, 2, 17, 32 }, }; for (size_t i = 0; i < arraysize(good_cases); i++) { SCOPED_TRACE(StringPrintf("Test[%" PRIuS "]: %s", i, good_cases[i].input)); diff --git a/net/ftp/ftp_util.cc b/net/ftp/ftp_util.cc index a0a47cf..e76adc0 100644 --- a/net/ftp/ftp_util.cc +++ b/net/ftp/ftp_util.cc @@ -177,4 +177,23 @@ bool FtpUtil::LsDateListingToTime(const string16& month, const string16& day, return true; } +// static +string16 FtpUtil::GetStringPartAfterColumns(const string16& text, int columns) { + size_t pos = 0; + + for (int i = 0; i < columns; i++) { + // Skip the leading whitespace. + while (pos < text.length() && isspace(text[pos])) + pos++; + + // Skip the actual text of i-th column. + while (pos < text.length() && !isspace(text[pos])) + pos++; + } + + string16 result(text.substr(pos)); + TrimWhitespace(result, TRIM_ALL, &result); + return result; +} + } // namespace diff --git a/net/ftp/ftp_util.h b/net/ftp/ftp_util.h index 518801b..5643606 100644 --- a/net/ftp/ftp_util.h +++ b/net/ftp/ftp_util.h @@ -38,6 +38,10 @@ class FtpUtil { const string16& day, const string16& rest, base::Time* time); + + // Skip |columns| columns from |text| (whitespace-delimited), and return the + // remaining part, without leading/trailing whitespace. + static string16 GetStringPartAfterColumns(const string16& text, int columns); }; } // namespace net diff --git a/net/ftp/ftp_util_unittest.cc b/net/ftp/ftp_util_unittest.cc index 46db873d..e929aed 100644 --- a/net/ftp/ftp_util_unittest.cc +++ b/net/ftp/ftp_util_unittest.cc @@ -150,4 +150,31 @@ TEST(FtpUtilTest, LsDateListingToTime) { } } +TEST(FtpUtilTest, GetStringPartAfterColumns) { + const struct { + const char* text; + int column; + const char* expected_result; + } kTestCases[] = { + { "", 0, "" }, + { "", 1, "" }, + { "foo abc", 0, "foo abc" }, + { "foo abc", 1, "abc" }, + { " foo abc", 0, "foo abc" }, + { " foo abc", 1, "abc" }, + { " foo abc", 2, "" }, + { " foo abc ", 0, "foo abc" }, + { " foo abc ", 1, "abc" }, + { " foo abc ", 2, "" }, + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); i++) { + SCOPED_TRACE(StringPrintf("Test[%" PRIuS "]: %s %d", + i, kTestCases[i].text, kTestCases[i].column)); + + EXPECT_EQ(ASCIIToUTF16(kTestCases[i].expected_result), + net::FtpUtil::GetStringPartAfterColumns( + ASCIIToUTF16(kTestCases[i].text), kTestCases[i].column)); + } +} + } // namespace |