diff options
-rw-r--r-- | net/data/ftp/dir-listing-ls-5 | 1 | ||||
-rw-r--r-- | net/data/ftp/dir-listing-ls-5.expected | 8 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_buffer.cc | 31 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_buffer.h | 4 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_buffer_unittest.cc | 1 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_parsers.cc | 12 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_parsers.h | 7 | ||||
-rw-r--r-- | net/ftp/ftp_directory_listing_parsers_unittest.cc | 3 |
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)); |