summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.cc18
-rw-r--r--net/ftp/ftp_directory_listing_parser_windows.cc11
-rw-r--r--net/ftp/ftp_directory_listing_parser_windows_unittest.cc3
-rw-r--r--net/ftp/ftp_util.cc19
-rw-r--r--net/ftp/ftp_util.h4
-rw-r--r--net/ftp/ftp_util_unittest.cc27
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