summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/data/ftp/dir-listing-ls-51
-rw-r--r--net/data/ftp/dir-listing-ls-5.expected8
-rw-r--r--net/ftp/ftp_directory_listing_buffer.cc31
-rw-r--r--net/ftp/ftp_directory_listing_buffer.h4
-rw-r--r--net/ftp/ftp_directory_listing_buffer_unittest.cc1
-rw-r--r--net/ftp/ftp_directory_listing_parsers.cc12
-rw-r--r--net/ftp/ftp_directory_listing_parsers.h7
-rw-r--r--net/ftp/ftp_directory_listing_parsers_unittest.cc3
8 files changed, 66 insertions, 1 deletions
diff --git a/net/data/ftp/dir-listing-ls-5 b/net/data/ftp/dir-listing-ls-5
new file mode 100644
index 0000000..87c4266
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-5
@@ -0,0 +1 @@
+drwxrwsr-x 4 501 501 4096 Feb 20 2007 pub
diff --git a/net/data/ftp/dir-listing-ls-5.expected b/net/data/ftp/dir-listing-ls-5.expected
new file mode 100644
index 0000000..3acbcf3
--- /dev/null
+++ b/net/data/ftp/dir-listing-ls-5.expected
@@ -0,0 +1,8 @@
+d
+pub
+-1
+2007
+2
+20
+0
+0
diff --git a/net/ftp/ftp_directory_listing_buffer.cc b/net/ftp/ftp_directory_listing_buffer.cc
index e41cb9e..19483d0 100644
--- a/net/ftp/ftp_directory_listing_buffer.cc
+++ b/net/ftp/ftp_directory_listing_buffer.cc
@@ -70,7 +70,16 @@ int FtpDirectoryListingBuffer::ProcessRemainingData() {
if (!buffer_.empty())
return ERR_INVALID_RESPONSE;
- return ParseLines();
+ rv = ParseLines();
+ if (rv != OK)
+ return rv;
+
+ rv = OnEndOfInput();
+ if (rv != OK)
+ return rv;
+
+ DCHECK(current_parser_);
+ return OK;
}
bool FtpDirectoryListingBuffer::EntryAvailable() const {
@@ -146,4 +155,24 @@ int FtpDirectoryListingBuffer::ParseLines() {
return OK;
}
+int FtpDirectoryListingBuffer::OnEndOfInput() {
+ ParserSet::iterator i = parsers_.begin();
+ while (i != parsers_.end()) {
+ if ((*i)->OnEndOfInput()) {
+ i++;
+ } else {
+ delete *i;
+ parsers_.erase(i++);
+ }
+ }
+
+ if (parsers_.size() != 1) {
+ current_parser_ = NULL;
+ return ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT;
+ }
+
+ current_parser_ = *parsers_.begin();
+ return OK;
+}
+
} // namespace net
diff --git a/net/ftp/ftp_directory_listing_buffer.h b/net/ftp/ftp_directory_listing_buffer.h
index 9489135..f71685c 100644
--- a/net/ftp/ftp_directory_listing_buffer.h
+++ b/net/ftp/ftp_directory_listing_buffer.h
@@ -57,6 +57,10 @@ class FtpDirectoryListingBuffer {
// Tries to parse full lines stored in |lines_|. Returns network error code.
int ParseLines();
+ // Called when we received the entire input. Propagates that info to remaining
+ // parsers. Returns network error code.
+ int OnEndOfInput();
+
// Detected encoding of the response (empty if unknown or ASCII).
std::string encoding_;
diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc
index 97a915e..d9da0cf 100644
--- a/net/ftp/ftp_directory_listing_buffer_unittest.cc
+++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc
@@ -22,6 +22,7 @@ TEST(FtpDirectoryListingBufferTest, Parse) {
"dir-listing-ls-2",
"dir-listing-ls-3",
"dir-listing-ls-4",
+ "dir-listing-ls-5",
"dir-listing-windows-1",
"dir-listing-windows-2",
"dir-listing-vms-1",
diff --git a/net/ftp/ftp_directory_listing_parsers.cc b/net/ftp/ftp_directory_listing_parsers.cc
index c2679d7..8963624 100644
--- a/net/ftp/ftp_directory_listing_parsers.cc
+++ b/net/ftp/ftp_directory_listing_parsers.cc
@@ -341,6 +341,10 @@ bool FtpLsDirectoryListingParser::ConsumeLine(const string16& line) {
return true;
}
+bool FtpLsDirectoryListingParser::OnEndOfInput() {
+ return true;
+}
+
bool FtpLsDirectoryListingParser::EntryAvailable() const {
return !entries_.empty();
}
@@ -381,6 +385,10 @@ bool FtpWindowsDirectoryListingParser::ConsumeLine(const string16& line) {
return true;
}
+bool FtpWindowsDirectoryListingParser::OnEndOfInput() {
+ return true;
+}
+
bool FtpWindowsDirectoryListingParser::EntryAvailable() const {
return !entries_.empty();
}
@@ -441,6 +449,10 @@ bool FtpVmsDirectoryListingParser::ConsumeLine(const string16& line) {
}
}
+bool FtpVmsDirectoryListingParser::OnEndOfInput() {
+ return (state_ == STATE_END);
+}
+
bool FtpVmsDirectoryListingParser::EntryAvailable() const {
return !entries_.empty();
}
diff --git a/net/ftp/ftp_directory_listing_parsers.h b/net/ftp/ftp_directory_listing_parsers.h
index e02bb1d..8b11ecb 100644
--- a/net/ftp/ftp_directory_listing_parsers.h
+++ b/net/ftp/ftp_directory_listing_parsers.h
@@ -38,6 +38,10 @@ class FtpDirectoryListingParser {
// Adds |line| to the internal parsing buffer. Returns true on success.
virtual bool ConsumeLine(const string16& line) = 0;
+ // Called after all input has been consumed. Returns true if the parser
+ // recognizes all received data as a valid listing.
+ virtual bool OnEndOfInput() = 0;
+
// Returns true if there is at least one FtpDirectoryListingEntry available.
virtual bool EntryAvailable() const = 0;
@@ -54,6 +58,7 @@ class FtpLsDirectoryListingParser : public FtpDirectoryListingParser {
// FtpDirectoryListingParser methods:
virtual FtpServerType GetServerType() const { return SERVER_LS; }
virtual bool ConsumeLine(const string16& line);
+ virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
virtual FtpDirectoryListingEntry PopEntry();
@@ -72,6 +77,7 @@ class FtpWindowsDirectoryListingParser : public FtpDirectoryListingParser {
// FtpDirectoryListingParser methods:
virtual FtpServerType GetServerType() const { return SERVER_WINDOWS; }
virtual bool ConsumeLine(const string16& line);
+ virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
virtual FtpDirectoryListingEntry PopEntry();
@@ -89,6 +95,7 @@ class FtpVmsDirectoryListingParser : public FtpDirectoryListingParser {
// FtpDirectoryListingParser methods:
virtual FtpServerType GetServerType() const { return SERVER_VMS; }
virtual bool ConsumeLine(const string16& line);
+ virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
virtual FtpDirectoryListingEntry PopEntry();
diff --git a/net/ftp/ftp_directory_listing_parsers_unittest.cc b/net/ftp/ftp_directory_listing_parsers_unittest.cc
index 19c6feb..80ddc7e 100644
--- a/net/ftp/ftp_directory_listing_parsers_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parsers_unittest.cc
@@ -68,6 +68,9 @@ TEST_F(FtpDirectoryListingParsersTest, Ls) {
{ "lrwxrwxrwx 1 0 0 3 Oct 12 13:37 mirror -> pub",
net::FtpDirectoryListingEntry::SYMLINK, "mirror", -1,
now_exploded.year, 10, 12, 13, 37 },
+ { "drwxrwsr-x 4 501 501 4096 Feb 20 2007 pub",
+ net::FtpDirectoryListingEntry::DIRECTORY, "pub", -1,
+ 2007, 2, 20, 0, 0 },
};
for (size_t i = 0; i < arraysize(good_cases); i++) {
SCOPED_TRACE(StringPrintf("Test[%" PRIuS "]: %s", i, good_cases[i].input));