summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/data/ftp/dir-listing-ls-118
-rw-r--r--net/data/ftp/dir-listing-ls-11.expected62
-rw-r--r--net/data/ftp/dir-listing-ls-128
-rw-r--r--net/data/ftp/dir-listing-ls-12.expected62
-rw-r--r--net/ftp/ftp_directory_listing_buffer_unittest.cc2
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.cc53
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.h5
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls_unittest.cc21
8 files changed, 204 insertions, 17 deletions
diff --git a/net/data/ftp/dir-listing-ls-11 b/net/data/ftp/dir-listing-ls-11
new file mode 100644
index 0000000..f81fda6
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-11
@@ -0,0 +1,8 @@
+total 14
+drwxr-xr-x 2 other 512 Feb 25 2009 beid
+lrwxrwxrwx 1 bin 9 May 1 2007 bin -> ./usr/bin
+d--x--x--x 2 sys 512 May 1 2007 dev
+d--x--x--x 5 sys 512 May 1 2007 etc
+drwxr-xr-x 2 sys 512 Mar 27 2009 pub
+drwxr-xr-x 3 other 512 Apr 11 2007 tigerd1
+d--x--x--x 6 sys 512 May 1 2007 usr
diff --git a/net/data/ftp/dir-listing-ls-11.expected b/net/data/ftp/dir-listing-ls-11.expected
new file mode 100644
index 0000000..82f1a9d
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-11.expected
@@ -0,0 +1,62 @@
+d
+beid
+-1
+2009
+2
+25
+0
+0
+
+l
+bin
+-1
+2007
+5
+1
+0
+0
+
+d
+dev
+-1
+2007
+5
+1
+0
+0
+
+d
+etc
+-1
+2007
+5
+1
+0
+0
+
+d
+pub
+-1
+2009
+3
+27
+0
+0
+
+d
+tigerd1
+-1
+2007
+4
+11
+0
+0
+
+d
+usr
+-1
+2007
+5
+1
+0
+0
diff --git a/net/data/ftp/dir-listing-ls-12 b/net/data/ftp/dir-listing-ls-12
new file mode 100644
index 0000000..7eee0bd
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-12
@@ -0,0 +1,8 @@
+total 14
+lrwxrwxrwx 1 other 7 Sep 1 2005 bin -> usr/bin
+dr-xr-xr-x 2 other 512 Aug 9 2004 dev
+dr-xr-xr-x 2 other 512 Sep 28 2006 etc
+drwxr-xr-x 2 other 512 Sep 28 2006 msgs
+drwxr-xr-x 53 other 1024 Jun 30 09:52 pub
+dr-xr-xr-x 5 other 512 Aug 9 2004 usr
+drwxr-xr-x 2 other 512 Aug 9 2004 var
diff --git a/net/data/ftp/dir-listing-ls-12.expected b/net/data/ftp/dir-listing-ls-12.expected
new file mode 100644
index 0000000..761f7f4
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-12.expected
@@ -0,0 +1,62 @@
+l
+bin
+-1
+2005
+9
+1
+0
+0
+
+d
+dev
+-1
+2004
+8
+9
+0
+0
+
+d
+etc
+-1
+2006
+9
+28
+0
+0
+
+d
+msgs
+-1
+2006
+9
+28
+0
+0
+
+d
+pub
+-1
+current
+6
+30
+9
+52
+
+d
+usr
+-1
+2004
+8
+9
+0
+0
+
+d
+var
+-1
+2004
+8
+9
+0
+0
diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc
index cf107b9..559256e 100644
--- a/net/ftp/ftp_directory_listing_buffer_unittest.cc
+++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc
@@ -28,6 +28,8 @@ TEST(FtpDirectoryListingBufferTest, Parse) {
"dir-listing-ls-8",
"dir-listing-ls-9",
"dir-listing-ls-10",
+ "dir-listing-ls-11",
+ "dir-listing-ls-12",
"dir-listing-netware-1",
"dir-listing-netware-2",
"dir-listing-vms-1",
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc
index 64feeed..cc09ca0 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -57,27 +57,49 @@ string16 GetStringPartAfterColumns(const string16& text, int columns) {
return result;
}
+bool DetectColumnOffset(const std::vector<string16>& columns, int* offset) {
+ base::Time time;
+
+ if (columns.size() >= 8 &&
+ net::FtpUtil::LsDateListingToTime(columns[5], columns[6], columns[7],
+ &time)) {
+ // Standard listing, exactly like ls -l.
+ *offset = 1;
+ return true;
+ }
+
+ if (columns.size() >= 7 &&
+ net::FtpUtil::LsDateListingToTime(columns[4], columns[5], columns[6],
+ &time)) {
+ // wu-ftpd listing, no "number of links" column.
+ *offset = 0;
+ return true;
+ }
+
+ // Unrecognized listing style.
+ return false;
+}
+
} // namespace
namespace net {
FtpDirectoryListingParserLs::FtpDirectoryListingParserLs()
: received_nonempty_line_(false),
- received_total_line_(false) {
+ received_total_line_(false),
+ column_offset_(-1) {
}
bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
+ std::vector<string16> columns;
+ SplitString(CollapseWhitespace(line, false), ' ', &columns);
+
if (line.empty() && !received_nonempty_line_) {
// Allow empty lines only at the beginning of the listing. For example VMS
// systems in Unix emulation mode add an empty line before the first listing
// entry.
return true;
}
- received_nonempty_line_ = true;
-
- std::vector<string16> columns;
- SplitString(CollapseWhitespace(line, false), ' ', &columns);
-
// Some FTP servers put a "total n" line at the beginning of the listing
// (n is an integer). Allow such a line, but only once, and only if it's
// the first non-empty line. Do not match the word exactly, because it may be
@@ -94,11 +116,14 @@ bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
return true;
}
+ if (!received_nonempty_line_ && !DetectColumnOffset(columns, &column_offset_))
+ return false;
+ received_nonempty_line_ = true;
// 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() < 9)
+ if (columns.size() < 8U + column_offset_)
return false;
if (!LooksLikeUnixPermissionsListing(columns[0]))
@@ -113,25 +138,21 @@ bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
entry.type = FtpDirectoryListingEntry::FILE;
}
- int number_of_links;
- if (!StringToInt(columns[1], &number_of_links))
- return false;
- if (number_of_links < 0)
- return false;
-
- if (!StringToInt64(columns[4], &entry.size))
+ if (!StringToInt64(columns[3 + column_offset_], &entry.size))
return false;
if (entry.size < 0)
return false;
if (entry.type != FtpDirectoryListingEntry::FILE)
entry.size = -1;
- if (!FtpUtil::LsDateListingToTime(columns[5], columns[6], columns[7],
+ if (!FtpUtil::LsDateListingToTime(columns[4 + column_offset_],
+ columns[5 + column_offset_],
+ columns[6 + column_offset_],
&entry.last_modified)) {
return false;
}
- entry.name = GetStringPartAfterColumns(line, 8);
+ entry.name = GetStringPartAfterColumns(line, 7 + 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_ls.h b/net/ftp/ftp_directory_listing_parser_ls.h
index 3fd0d32..50e0a1f 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.h
+++ b/net/ftp/ftp_directory_listing_parser_ls.h
@@ -30,6 +30,11 @@ class FtpDirectoryListingParserLs : public FtpDirectoryListingParser {
// integer. Only one such header is allowed per listing.
bool received_total_line_;
+ // There is a variant of the listing served by wu-ftpd which doesn't contain
+ // the "number of links" column (the second column in a "standard" ls -l
+ // listing). Store an offset to reference later columns.
+ int column_offset_;
+
std::queue<FtpDirectoryListingEntry> entries_;
DISALLOW_COPY_AND_ASSIGN(FtpDirectoryListingParserLs);
diff --git a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
index a58b839..f0ec455 100644
--- a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -40,6 +40,20 @@ TEST_F(FtpDirectoryListingParserLsTest, Good) {
{ "-rw-r--r-- 1 2 3 3447432 May 18 2009 Foo - Manual.pdf",
net::FtpDirectoryListingEntry::FILE, "Foo - Manual.pdf", 3447432,
2009, 5, 18, 0, 0 },
+
+ // Tests for the wu-ftpd variant:
+ { "drwxr-xr-x 2 sys 512 Mar 27 2009 pub",
+ net::FtpDirectoryListingEntry::DIRECTORY, "pub", -1,
+ 2009, 3, 27, 0, 0 },
+ { "lrwxrwxrwx 0 0 26 Sep 18 2008 pub -> vol/1/.CLUSTER/var_ftp/pub",
+ net::FtpDirectoryListingEntry::SYMLINK, "pub", -1,
+ 2008, 9, 18, 0, 0 },
+ { "drwxr-xr-x (?) (?) 4096 Apr 8 2007 jigdo",
+ net::FtpDirectoryListingEntry::DIRECTORY, "jigdo", -1,
+ 2007, 4, 8, 0, 0 },
+ { "-rw-r--r-- 2 3 3447432 May 18 2009 Foo - Manual.pdf",
+ net::FtpDirectoryListingEntry::FILE, "Foo - Manual.pdf", 3447432,
+ 2009, 5, 18, 0, 0 },
};
for (size_t i = 0; i < arraysize(good_cases); i++) {
SCOPED_TRACE(StringPrintf("Test[%" PRIuS "]: %s", i, good_cases[i].input));
@@ -52,11 +66,16 @@ TEST_F(FtpDirectoryListingParserLsTest, Good) {
TEST_F(FtpDirectoryListingParserLsTest, Bad) {
const char* bad_cases[] = {
"garbage",
+ "-rw-r--r-- ftp ftp",
+ "-rw-r--rgb ftp ftp 528 Nov 01 2007 README",
+ "-rw-rgbr-- ftp ftp 528 Nov 01 2007 README",
+ "qrwwr--r-- ftp ftp 528 Nov 01 2007 README",
+ "-rw-r--r-- ftp ftp -528 Nov 01 2007 README",
+ "-rw-r--r-- ftp ftp 528 Foo 01 2007 README",
"-rw-r--r-- 1 ftp ftp",
"-rw-r--rgb 1 ftp ftp 528 Nov 01 2007 README",
"-rw-rgbr-- 1 ftp ftp 528 Nov 01 2007 README",
"qrwwr--r-- 1 ftp ftp 528 Nov 01 2007 README",
- "-rw-r--r-- -1 ftp ftp 528 Nov 01 2007 README",
"-rw-r--r-- 1 ftp ftp -528 Nov 01 2007 README",
"-rw-r--r-- 1 ftp ftp 528 Foo 01 2007 README",
};