From e8b0d041d4227741077bffb8dbf36a070dd5120e Mon Sep 17 00:00:00 2001 From: "phajdan.jr@chromium.org" Date: Tue, 28 Sep 2010 09:28:01 +0000 Subject: FTP: fix directory listing parser for ftp.usa.hp.com BUG=56547 TEST=net_unittests Review URL: http://codereview.chromium.org/3448029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60765 0039d316-1c4b-4281-b951-d872f2087c98 --- net/ftp/ftp_directory_listing_buffer.cc | 8 +-- net/ftp/ftp_directory_listing_buffer_unittest.cc | 7 +-- net/ftp/ftp_directory_listing_parser_hprc.cc | 58 ++++++++++++++++++++++ net/ftp/ftp_directory_listing_parser_hprc.h | 45 +++++++++++++++++ .../ftp_directory_listing_parser_hprc_unittest.cc | 54 ++++++++++++++++++++ .../ftp_directory_listing_parser_ls_unittest.cc | 1 + .../ftp_directory_listing_parser_mlsd_unittest.cc | 1 + ...tp_directory_listing_parser_netware_unittest.cc | 1 + net/ftp/ftp_directory_listing_parser_unittest.h | 4 +- net/ftp/ftp_server_type_histograms.h | 1 + 10 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 net/ftp/ftp_directory_listing_parser_hprc.cc create mode 100644 net/ftp/ftp_directory_listing_parser_hprc.h create mode 100644 net/ftp/ftp_directory_listing_parser_hprc_unittest.cc (limited to 'net/ftp') diff --git a/net/ftp/ftp_directory_listing_buffer.cc b/net/ftp/ftp_directory_listing_buffer.cc index 8399f13..a173399 100644 --- a/net/ftp/ftp_directory_listing_buffer.cc +++ b/net/ftp/ftp_directory_listing_buffer.cc @@ -1,6 +1,6 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this -// source code is governed by a BSD-style license that can be found in the -// LICENSE file. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "net/ftp/ftp_directory_listing_buffer.h" @@ -9,6 +9,7 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "net/base/net_errors.h" +#include "net/ftp/ftp_directory_listing_parser_hprc.h" #include "net/ftp/ftp_directory_listing_parser_ls.h" #include "net/ftp/ftp_directory_listing_parser_mlsd.h" #include "net/ftp/ftp_directory_listing_parser_netware.h" @@ -20,6 +21,7 @@ namespace net { FtpDirectoryListingBuffer::FtpDirectoryListingBuffer( const base::Time& current_time) : current_parser_(NULL) { + parsers_.insert(new FtpDirectoryListingParserHprc(current_time)); parsers_.insert(new FtpDirectoryListingParserLs(current_time)); parsers_.insert(new FtpDirectoryListingParserMlsd()); parsers_.insert(new FtpDirectoryListingParserNetware(current_time)); diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc index ff7aedf..13b3cce 100644 --- a/net/ftp/ftp_directory_listing_buffer_unittest.cc +++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc @@ -19,6 +19,9 @@ namespace { TEST(FtpDirectoryListingBufferTest, Parse) { const char* test_files[] = { + "dir-listing-hprc-1", + "dir-listing-hprc-2", + "dir-listing-hprc-3", "dir-listing-ls-1", "dir-listing-ls-1-utf8", "dir-listing-ls-2", @@ -57,7 +60,7 @@ TEST(FtpDirectoryListingBufferTest, Parse) { test_dir = test_dir.AppendASCII("ftp"); base::Time mock_current_time; - ASSERT_TRUE(base::Time::FromString(L"Tue, 15 Nov 1994 12:45:26 GMT", + ASSERT_TRUE(base::Time::FromString(L"Tue, 15 Nov 1994 12:45:26", &mock_current_time)); for (size_t i = 0; i < arraysize(test_files); i++) { @@ -122,8 +125,6 @@ TEST(FtpDirectoryListingBufferTest, Parse) { EXPECT_EQ(day_of_month, time_exploded.day_of_month); EXPECT_EQ(hour, time_exploded.hour); EXPECT_EQ(minute, time_exploded.minute); - EXPECT_EQ(0, time_exploded.second); - EXPECT_EQ(0, time_exploded.millisecond); } EXPECT_FALSE(buffer.EntryAvailable()); } diff --git a/net/ftp/ftp_directory_listing_parser_hprc.cc b/net/ftp/ftp_directory_listing_parser_hprc.cc new file mode 100644 index 0000000..b65ec68 --- /dev/null +++ b/net/ftp/ftp_directory_listing_parser_hprc.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ftp/ftp_directory_listing_parser_hprc.h" + +#include "base/logging.h" +#include "base/time.h" + +namespace net { + +FtpDirectoryListingParserHprc::FtpDirectoryListingParserHprc( + const base::Time& current_time) + : current_time_(current_time) { +} + +FtpServerType FtpDirectoryListingParserHprc::GetServerType() const { + return SERVER_HPRC; +} + +bool FtpDirectoryListingParserHprc::ConsumeLine(const string16& line) { + if (line.empty()) + return false; + + // All lines begin with a space. + if (line[0] != ' ') + return false; + + FtpDirectoryListingEntry entry; + entry.name = line.substr(1); + + // We don't know anything beyond the file name, so just pick some arbitrary + // values. + // TODO(phajdan.jr): consider adding an UNKNOWN entry type. + entry.type = FtpDirectoryListingEntry::FILE; + entry.size = 0; + entry.last_modified = current_time_; + + entries_.push(entry); + return true; +} + +bool FtpDirectoryListingParserHprc::OnEndOfInput() { + return true; +} + +bool FtpDirectoryListingParserHprc::EntryAvailable() const { + return !entries_.empty(); +} + +FtpDirectoryListingEntry FtpDirectoryListingParserHprc::PopEntry() { + DCHECK(EntryAvailable()); + FtpDirectoryListingEntry entry = entries_.front(); + entries_.pop(); + return entry; +} + +} // namespace net diff --git a/net/ftp/ftp_directory_listing_parser_hprc.h b/net/ftp/ftp_directory_listing_parser_hprc.h new file mode 100644 index 0000000..73b5195 --- /dev/null +++ b/net/ftp/ftp_directory_listing_parser_hprc.h @@ -0,0 +1,45 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_ +#define NET_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_ +#pragma once + +#include + +#include "base/basictypes.h" +#include "base/time.h" +#include "net/ftp/ftp_directory_listing_parser.h" + +namespace net { + +// Parser for directory listings served by HPRC, +// see http://hprc.external.hp.com/ and http://crbug.com/56547. +class FtpDirectoryListingParserHprc : public FtpDirectoryListingParser { + public: + // Constructor. When we need to provide the last modification time + // that we don't know, |current_time| will be used. This allows passing + // a specific date during testing. + explicit FtpDirectoryListingParserHprc(const base::Time& current_time); + + // FtpDirectoryListingParser methods: + virtual FtpServerType GetServerType() const; + virtual bool ConsumeLine(const string16& line); + virtual bool OnEndOfInput(); + virtual bool EntryAvailable() const; + virtual FtpDirectoryListingEntry PopEntry(); + + private: + // Store the current time. We use it in place of last modification time + // that is unknown (the server doesn't send it). + const base::Time current_time_; + + std::queue entries_; + + DISALLOW_COPY_AND_ASSIGN(FtpDirectoryListingParserHprc); +}; + +} // namespace net + +#endif // NET_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_ diff --git a/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc b/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc new file mode 100644 index 0000000..2cdedeb --- /dev/null +++ b/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ftp/ftp_directory_listing_parser_unittest.h" + +#include "base/format_macros.h" +#include "base/string_util.h" +#include "base/stringprintf.h" +#include "net/ftp/ftp_directory_listing_parser_hprc.h" + +namespace { + +typedef net::FtpDirectoryListingParserTest FtpDirectoryListingParserHprcTest; + +TEST_F(FtpDirectoryListingParserHprcTest, Good) { + base::Time mock_current_time; + ASSERT_TRUE(base::Time::FromString(L"Tue, 15 Nov 1994 12:45:26", + &mock_current_time)); + + const struct SingleLineTestData good_cases[] = { + { " .welcome", + net::FtpDirectoryListingEntry::FILE, ".welcome", 0, + 1994, 11, 15, 12, 45 }, + }; + for (size_t i = 0; i < arraysize(good_cases); i++) { + SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i, + good_cases[i].input)); + + net::FtpDirectoryListingParserHprc parser(mock_current_time); + RunSingleLineTestCase(&parser, good_cases[i]); + } +} + +TEST_F(FtpDirectoryListingParserHprcTest, Bad) { + base::Time mock_current_time; + ASSERT_TRUE(base::Time::FromString(L"Tue, 15 Nov 1994 12:45:26", + &mock_current_time)); + + const char* bad_cases[] = { + "", + "test", + "-rw-r--r-- 1 ftp ftp 528 Nov 01 2007 README", + "d [RWCEAFMS] ftpadmin 512 Jan 29 2004 pub", + "TEST.DIR;1 1 4-MAR-1999 22:14:34 [UCX$NOBO,ANONYMOUS] (RWE,RWE,RWE,RWE)", + "type=dir;modify=20010414155237;UNIX.mode=0555;unique=6ag5b4e400; etc", + }; + for (size_t i = 0; i < arraysize(bad_cases); i++) { + net::FtpDirectoryListingParserHprc parser(mock_current_time); + EXPECT_FALSE(parser.ConsumeLine(UTF8ToUTF16(bad_cases[i]))) << bad_cases[i]; + } +} + +} // namespace diff --git a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc index 2b57b40..06f1adf 100644 --- a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc @@ -95,6 +95,7 @@ TEST_F(FtpDirectoryListingParserLsTest, Bad) { &mock_current_time)); const char* bad_cases[] = { + " foo", "garbage", "-rw-r--r-- ftp ftp", "-rw-r--rgb ftp ftp 528 Nov 01 2007 README", diff --git a/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc b/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc index 1a01f27..309b4fb 100644 --- a/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc @@ -48,6 +48,7 @@ TEST_F(FtpDirectoryListingParserMlsdTest, Bad) { ";", "; ", " ;", + " foo", "garbage", "total 5", "type=file;size=380565;modify=20030606190749;README", diff --git a/net/ftp/ftp_directory_listing_parser_netware_unittest.cc b/net/ftp/ftp_directory_listing_parser_netware_unittest.cc index f5e4a35..aa803db 100644 --- a/net/ftp/ftp_directory_listing_parser_netware_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_netware_unittest.cc @@ -44,6 +44,7 @@ TEST_F(FtpDirectoryListingParserNetwareTest, Bad) { &mock_current_time)); const char* bad_cases[] = { + " foo", "garbage", "d [] ftpadmin 512 Jan 29 2004 pub", "d [XGARBAGE] ftpadmin 512 Jan 29 2004 pub", diff --git a/net/ftp/ftp_directory_listing_parser_unittest.h b/net/ftp/ftp_directory_listing_parser_unittest.h index c31546e..98387f2 100644 --- a/net/ftp/ftp_directory_listing_parser_unittest.h +++ b/net/ftp/ftp_directory_listing_parser_unittest.h @@ -40,13 +40,13 @@ class FtpDirectoryListingParserTest : public testing::Test { base::Time::Exploded time_exploded; entry.last_modified.LocalExplode(&time_exploded); + + // Only test members displayed on the directory listing. EXPECT_EQ(test_case.year, time_exploded.year); EXPECT_EQ(test_case.month, time_exploded.month); EXPECT_EQ(test_case.day_of_month, time_exploded.day_of_month); EXPECT_EQ(test_case.hour, time_exploded.hour); EXPECT_EQ(test_case.minute, time_exploded.minute); - EXPECT_EQ(0, time_exploded.second); - EXPECT_EQ(0, time_exploded.millisecond); } private: diff --git a/net/ftp/ftp_server_type_histograms.h b/net/ftp/ftp_server_type_histograms.h index 72d3c78..6a856b1 100644 --- a/net/ftp/ftp_server_type_histograms.h +++ b/net/ftp/ftp_server_type_histograms.h @@ -25,6 +25,7 @@ enum FtpServerType { SERVER_VMS = 11, // Server using VMS listing style. SERVER_NETWARE = 12, // Server using Netware listing style. SERVER_MLSD = 13, // Server using MLSD listing (RFC-3659). + SERVER_HPRC = 14, // Server using HPRC listing (http://crbug.com/56547). NUM_OF_SERVER_TYPES }; -- cgit v1.1