summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/data/ftp/dir-listing-windows-12
-rw-r--r--net/data/ftp/dir-listing-windows-1.expected17
-rw-r--r--net/data/ftp/dir-listing-windows-216
-rw-r--r--net/data/ftp/dir-listing-windows-2.expected143
-rw-r--r--net/ftp/ftp_directory_listing_buffer.cc1
-rw-r--r--net/ftp/ftp_directory_listing_buffer_unittest.cc2
-rw-r--r--net/ftp/ftp_directory_listing_parsers.cc92
-rw-r--r--net/ftp/ftp_directory_listing_parsers.h15
-rw-r--r--net/ftp/ftp_directory_listing_parsers_unittest.cc55
9 files changed, 341 insertions, 2 deletions
diff --git a/net/data/ftp/dir-listing-windows-1 b/net/data/ftp/dir-listing-windows-1
new file mode 100644
index 0000000..a8ff16d
--- /dev/null
+++ b/net/data/ftp/dir-listing-windows-1
@@ -0,0 +1,2 @@
+11-02-09 05:32PM <DIR> NT
+01-06-09 02:42PM 458 Readme.txt
diff --git a/net/data/ftp/dir-listing-windows-1.expected b/net/data/ftp/dir-listing-windows-1.expected
new file mode 100644
index 0000000..8fbbb48
--- /dev/null
+++ b/net/data/ftp/dir-listing-windows-1.expected
@@ -0,0 +1,17 @@
+d
+NT
+-1
+2009
+11
+2
+17
+32
+
+-
+Readme.txt
+458
+2009
+1
+6
+14
+42
diff --git a/net/data/ftp/dir-listing-windows-2 b/net/data/ftp/dir-listing-windows-2
new file mode 100644
index 0000000..f62fea4
--- /dev/null
+++ b/net/data/ftp/dir-listing-windows-2
@@ -0,0 +1,16 @@
+05-18-09 11:07AM <DIR> beta
+01-06-09 04:25PM <DIR> cdrom
+01-06-09 02:38PM 129 checkdownload.html
+08-19-09 11:23AM <DIR> Digital_Media_Player
+12-29-08 10:27PM <DIR> LiveUpdate
+08-20-09 04:34PM <DIR> mb
+01-06-09 02:38PM 83933 Mb.eng
+11-04-09 03:42PM <DIR> misc
+06-12-09 04:20PM 462 Path.idx
+12-30-08 07:41AM <DIR> PDA
+01-06-09 02:38PM 2625 Platform.idx
+12-30-08 07:41AM <DIR> print
+01-06-09 02:42PM 458 Readme.txt
+10-28-09 02:27PM <DIR> server
+12-30-08 08:59AM <DIR> vga
+02-03-09 04:42PM 1951823 VH203_FR.pdf
diff --git a/net/data/ftp/dir-listing-windows-2.expected b/net/data/ftp/dir-listing-windows-2.expected
new file mode 100644
index 0000000..81388ee
--- /dev/null
+++ b/net/data/ftp/dir-listing-windows-2.expected
@@ -0,0 +1,143 @@
+d
+beta
+-1
+2009
+5
+18
+11
+7
+
+d
+cdrom
+-1
+2009
+1
+6
+16
+25
+
+-
+checkdownload.html
+129
+2009
+1
+6
+14
+38
+
+d
+Digital_Media_Player
+-1
+2009
+8
+19
+11
+23
+
+d
+LiveUpdate
+-1
+2008
+12
+29
+22
+27
+
+d
+mb
+-1
+2009
+8
+20
+16
+34
+
+-
+Mb.eng
+83933
+2009
+1
+6
+14
+38
+
+d
+misc
+-1
+2009
+11
+4
+15
+42
+
+-
+Path.idx
+462
+2009
+6
+12
+16
+20
+
+d
+PDA
+-1
+2008
+12
+30
+7
+41
+
+-
+Platform.idx
+2625
+2009
+1
+6
+14
+38
+
+d
+print
+-1
+2008
+12
+30
+7
+41
+
+-
+Readme.txt
+458
+2009
+1
+6
+14
+42
+
+d
+server
+-1
+2009
+10
+28
+14
+27
+
+d
+vga
+-1
+2008
+12
+30
+8
+59
+
+-
+VH203_FR.pdf
+1951823
+2009
+2
+3
+16
+42
diff --git a/net/ftp/ftp_directory_listing_buffer.cc b/net/ftp/ftp_directory_listing_buffer.cc
index d7833e8..8e3ee39 100644
--- a/net/ftp/ftp_directory_listing_buffer.cc
+++ b/net/ftp/ftp_directory_listing_buffer.cc
@@ -42,6 +42,7 @@ namespace net {
FtpDirectoryListingBuffer::FtpDirectoryListingBuffer()
: current_parser_(NULL) {
parsers_.insert(new FtpLsDirectoryListingParser());
+ parsers_.insert(new FtpWindowsDirectoryListingParser());
parsers_.insert(new FtpVmsDirectoryListingParser());
}
diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc
index 00c37963..9cf557f 100644
--- a/net/ftp/ftp_directory_listing_buffer_unittest.cc
+++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc
@@ -21,6 +21,8 @@ TEST(FtpDirectoryListingBufferTest, Parse) {
"dir-listing-ls-2",
"dir-listing-ls-3",
"dir-listing-ls-4",
+ "dir-listing-windows-1",
+ "dir-listing-windows-2",
"dir-listing-vms-1",
"dir-listing-vms-2",
"dir-listing-vms-3",
diff --git a/net/ftp/ftp_directory_listing_parsers.cc b/net/ftp/ftp_directory_listing_parsers.cc
index 4149390..c2679d7 100644
--- a/net/ftp/ftp_directory_listing_parsers.cc
+++ b/net/ftp/ftp_directory_listing_parsers.cc
@@ -88,6 +88,54 @@ bool UnixDateListingToTime(const std::vector<string16>& columns,
return true;
}
+bool WindowsDateListingToTime(const std::vector<string16>& columns,
+ base::Time* time) {
+ DCHECK_EQ(4U, columns.size());
+
+ base::Time::Exploded time_exploded = { 0 };
+
+ // Date should be in format MM-DD-YY[YY].
+ std::vector<string16> date_parts;
+ SplitString(columns[0], '-', &date_parts);
+ if (date_parts.size() != 3)
+ return false;
+ if (!StringToInt(date_parts[0], &time_exploded.month))
+ return false;
+ if (!StringToInt(date_parts[1], &time_exploded.day_of_month))
+ return false;
+ if (!StringToInt(date_parts[2], &time_exploded.year))
+ return false;
+ if (time_exploded.year < 0)
+ return false;
+ // If year has only two digits then assume that 00-79 is 2000-2079,
+ // and 80-99 is 1980-1999.
+ if (time_exploded.year < 80)
+ time_exploded.year += 2000;
+ else if (time_exploded.year < 100)
+ time_exploded.year += 1900;
+
+ // Time should be in format HH:MM(AM|PM)
+ if (columns[1].length() != 7)
+ return false;
+ std::vector<string16> time_parts;
+ SplitString(columns[1].substr(0, 5), ':', &time_parts);
+ if (time_parts.size() != 2)
+ return false;
+ if (!StringToInt(time_parts[0], &time_exploded.hour))
+ return false;
+ if (!StringToInt(time_parts[1], &time_exploded.minute))
+ return false;
+ string16 am_or_pm(columns[1].substr(5, 2));
+ if (EqualsASCII(am_or_pm, "PM"))
+ time_exploded.hour += 12;
+ else if (!EqualsASCII(am_or_pm, "AM"))
+ return false;
+
+ // We don't know the time zone of the server, so just use local time.
+ *time = base::Time::FromLocalExploded(time_exploded);
+ return true;
+}
+
// Converts the filename component in listing to the filename we can display.
// Returns true on success.
bool ParseVmsFilename(const string16& raw_filename, string16* parsed_filename,
@@ -109,7 +157,7 @@ bool ParseVmsFilename(const string16& raw_filename, string16* parsed_filename,
SplitString(listing_parts[0], '.', &filename_parts);
if (filename_parts.size() != 2)
return false;
- if (filename_parts[1] == ASCIIToUTF16("DIR")) {
+ if (EqualsASCII(filename_parts[1], "DIR")) {
*parsed_filename = StringToLowerASCII(filename_parts[0]);
*is_directory = true;
} else {
@@ -252,7 +300,7 @@ bool FtpLsDirectoryListingParser::ConsumeLine(const string16& line) {
SplitString(CollapseWhitespace(line, false), ' ', &columns);
if (columns.size() == 11) {
// Check if it is a symlink.
- if (columns[9] != ASCIIToUTF16("->"))
+ if (!EqualsASCII(columns[9], "->"))
return false;
// Drop the symlink target from columns, we don't use it.
@@ -303,6 +351,46 @@ FtpDirectoryListingEntry FtpLsDirectoryListingParser::PopEntry() {
return entry;
}
+FtpWindowsDirectoryListingParser::FtpWindowsDirectoryListingParser() {
+}
+
+bool FtpWindowsDirectoryListingParser::ConsumeLine(const string16& line) {
+ std::vector<string16> columns;
+ SplitString(CollapseWhitespace(line, false), ' ', &columns);
+ if (columns.size() != 4)
+ return false;
+
+ FtpDirectoryListingEntry entry;
+ entry.name = columns[3];
+
+ if (EqualsASCII(columns[2], "<DIR>")) {
+ entry.type = FtpDirectoryListingEntry::DIRECTORY;
+ entry.size = -1;
+ } else {
+ entry.type = FtpDirectoryListingEntry::FILE;
+ if (!StringToInt64(columns[2], &entry.size))
+ return false;
+ if (entry.size < 0)
+ return false;
+ }
+
+ if (!WindowsDateListingToTime(columns, &entry.last_modified))
+ return false;
+
+ entries_.push(entry);
+ return true;
+}
+
+bool FtpWindowsDirectoryListingParser::EntryAvailable() const {
+ return !entries_.empty();
+}
+
+FtpDirectoryListingEntry FtpWindowsDirectoryListingParser::PopEntry() {
+ FtpDirectoryListingEntry entry = entries_.front();
+ entries_.pop();
+ return entry;
+}
+
FtpVmsDirectoryListingParser::FtpVmsDirectoryListingParser()
: state_(STATE_INITIAL),
last_is_directory_(false) {
diff --git a/net/ftp/ftp_directory_listing_parsers.h b/net/ftp/ftp_directory_listing_parsers.h
index 2cf0c4f..62a23cf 100644
--- a/net/ftp/ftp_directory_listing_parsers.h
+++ b/net/ftp/ftp_directory_listing_parsers.h
@@ -62,6 +62,21 @@ class FtpLsDirectoryListingParser : public FtpDirectoryListingParser {
DISALLOW_COPY_AND_ASSIGN(FtpLsDirectoryListingParser);
};
+class FtpWindowsDirectoryListingParser : public FtpDirectoryListingParser {
+ public:
+ FtpWindowsDirectoryListingParser();
+
+ // FtpDirectoryListingParser methods:
+ virtual bool ConsumeLine(const string16& line);
+ virtual bool EntryAvailable() const;
+ virtual FtpDirectoryListingEntry PopEntry();
+
+ private:
+ std::queue<FtpDirectoryListingEntry> entries_;
+
+ DISALLOW_COPY_AND_ASSIGN(FtpWindowsDirectoryListingParser);
+};
+
// Parser for VMS-style directory listing (including variants).
class FtpVmsDirectoryListingParser : public FtpDirectoryListingParser {
public:
diff --git a/net/ftp/ftp_directory_listing_parsers_unittest.cc b/net/ftp/ftp_directory_listing_parsers_unittest.cc
index 0d0c1f5..da5ca11 100644
--- a/net/ftp/ftp_directory_listing_parsers_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parsers_unittest.cc
@@ -91,6 +91,61 @@ TEST_F(FtpDirectoryListingParsersTest, Ls) {
}
}
+TEST_F(FtpDirectoryListingParsersTest, Windows) {
+ base::Time::Exploded now_exploded;
+ base::Time::Now().LocalExplode(&now_exploded);
+
+ const struct SingleLineTestData good_cases[] = {
+ { "11-02-09 05:32PM <DIR> NT",
+ net::FtpDirectoryListingEntry::DIRECTORY, "NT", -1,
+ 2009, 11, 2, 17, 32 },
+ { "01-06-09 02:42PM 458 Readme.txt",
+ net::FtpDirectoryListingEntry::FILE, "Readme.txt", 458,
+ 2009, 1, 6, 14, 42 },
+ { "01-06-09 02:42AM 1 Readme.txt",
+ net::FtpDirectoryListingEntry::FILE, "Readme.txt", 1,
+ 2009, 1, 6, 2, 42 },
+ { "01-06-01 02:42AM 458 Readme.txt",
+ net::FtpDirectoryListingEntry::FILE, "Readme.txt", 458,
+ 2001, 1, 6, 2, 42 },
+ { "01-06-00 02:42AM 458 Corner1.txt",
+ net::FtpDirectoryListingEntry::FILE, "Corner1.txt", 458,
+ 2000, 1, 6, 2, 42 },
+ { "01-06-99 02:42AM 458 Corner2.txt",
+ net::FtpDirectoryListingEntry::FILE, "Corner2.txt", 458,
+ 1999, 1, 6, 2, 42 },
+ { "01-06-80 02:42AM 458 Corner3.txt",
+ net::FtpDirectoryListingEntry::FILE, "Corner3.txt", 458,
+ 1980, 1, 6, 2, 42 },
+ { "01-06-79 02:42AM 458 Corner4",
+ net::FtpDirectoryListingEntry::FILE, "Corner4", 458,
+ 2079, 1, 6, 2, 42 },
+ { "01-06-1979 02:42AM 458 Readme.txt",
+ net::FtpDirectoryListingEntry::FILE, "Readme.txt", 458,
+ 1979, 1, 6, 2, 42 },
+ };
+ for (size_t i = 0; i < arraysize(good_cases); i++) {
+ SCOPED_TRACE(StringPrintf("Test[%d]: %s", i, good_cases[i].input));
+
+ net::FtpWindowsDirectoryListingParser parser;
+ RunSingleLineTestCase(&parser, good_cases[i]);
+ }
+
+ const char* bad_cases[] = {
+ "",
+ "garbage",
+ "11-02-09 05:32PM <GARBAGE> NT",
+ "11-02-09 05:32 <DIR> NT",
+ "11-FEB-09 05:32PM <DIR> NT",
+ "11-02 05:32PM <DIR> NT",
+ "11-02-09 05:32PM -1 NT",
+ };
+ for (size_t i = 0; i < arraysize(bad_cases); i++) {
+ net::FtpWindowsDirectoryListingParser parser;
+ EXPECT_FALSE(parser.ConsumeLine(UTF8ToUTF16(bad_cases[i]))) << bad_cases[i];
+ }
+}
+
TEST_F(FtpDirectoryListingParsersTest, Vms) {
const struct SingleLineTestData good_cases[] = {
{ "README.TXT;4 2 18-APR-2000 10:40:39.90",